Rate This Document
Findability
Accuracy
Completeness
Readability

Packaging Script

In the actual Nginx migration scenario, some configuration files and static files are stored outside the Nginx installation path. To facilitate source component packaging, a packaging script is provided for reference. The script packages the source components stored outside the Nginx installation path to the /Packaging_path/Nginx_installation_path/sbin/source_related directory according to the original directory structure.

  • This script is only a packaging example and does not involve risky operations or cause source code leak.
  • This script supports only Nginx that is compiled from the source code with its binary file stored in the Nginx_installation_path/sbin directory.
  • The tool cannot automatically migrate Nginx installed using an RPM package. Perform a manual migration instead.
  1. Create an .sh script file (for example, pack_nginx_sources.sh) in any directory on the source VM. For details about the script content, see pack_nginx_sources.sh.
  2. Run the script to start packaging. The generated .tar package is stored in the /home directory.
    1
    bash /path/to/pack_nginx_sources.sh /usr/local/nginx
    

    If the following information is displayed, the packaging is successful:

    Copying /usr/local/nginx to /home/nginx_mig_tmp ...
     Getting installation configure command paths...
    configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module --with-http_gzip_static_module --with-http_stub_status_module
     Getting startup config file...
    root      2864 32744  0 01:49 pts/1    00:00:00 bash pack_nginx_sources.sh /usr/local/nginx
    root      2881  2864  0 01:49 pts/1    00:00:00 grep nginx
     Scanning included sources in config file...
    [conf file]: /home/nginx_mig_tmp/nginx/conf/fastcgi.conf
    [conf file]: /home/nginx_mig_tmp/nginx/conf/nginx.conf
     Packing tar...
    Nginx related components are packaged into nginx_migration.tar.
    Note: Please manually check and remove unrelated files/dirs if needed.
    Please manually upload it to the node server and extract it using the command: tar xvf nginx_migration.tar -C /custom_path
    • /path/to: path to the script.
    • /usr/local/nginx: absolute path to the source Nginx installation directory. Replace it with the actual one.
    • If Nginx is started using a specified configuration file (-c option) and no binary file exists in the installation path, enter the Nginx binary path as prompted to package binary-related configuration files.
    If you create a script on Windows and use it on Linux, the following error message may be displayed. This is because the two OSs use different newline characters. To rectify this error, perform the following steps:
    -bash: ./pack_nginx_sources.sh: /bin/bash^M: bad interpreter: No such file or directory
    1. Install dos2unix.
      1
      yum install dos2unix
      
    2. After the installation is successful, run the following command:
      1
      dos2unix pack_nginx_sources.sh
      
    3. After the execution is complete, restart the script.
    If no Yum source is available and the installation fails, run the following command. After the execution is complete, restart the script.
    sed -i 's/\r//g' pack_nginx_sources.sh
  3. After the packaging is complete, delete the /home/nginx_mig_tmp directory.
  4. Obtain the source components using either of the following methods:
    • If you select the Upload source component package option, return to the Add Component Information tab, and click Upload next to Upload source component package to upload the source component package.
    • If you select the Obtain from node server option, run the following command to decompress the source component package.
      1. Log in to the tool through SSH and upload the package to the user-defined directory on Target Node.
      2. Go to the directory that stores the package.
        1
        cd User-defined_directory
        
      3. Decompress the source component package.
        1
        tar xvf nginx_migration.tar
        
      4. After the decompression is complete, you can run the following command to delete the source component package.
        1
        rm -f nginx_migration.tar
        
      5. Set the path to the decompressed file as the source component path.

pack_nginx_sources.sh

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/bin/bash

# Check the command line parameters and ensure that the absolute path to the source Nginx installation directory is provided.
if [ $# -ne 1 ]; then
     echo "Usage: $0 <source_nginx_install_dir>"
     exit 1
fi

source_nginx_dir="$1"
source_nginx_binary="$source_nginx_dir/sbin/nginx"
temp_dir="/home/nginx_mig_tmp"
source_nginx_tmp="$temp_dir/$(basename "$source_nginx_dir")"
migration_tar="nginx_migration.tar"

if [ ! -d "$source_nginx_dir" ]; then
     echo "The parameter entered is not a valid directory."
     echo "Usage: $0 <source_nginx_install_dir>"
     exit 1
fi

if [ ! -d "$source_nginx_dir/sbin" ]; then
    echo "The source Nginx installation path does not contain the sbin directory."
    echo "Usage: $0 <source_nginx_install_dir>"
    echo "Notice: This script only supports the source Nginx binary stored in \"<source_nginx_install_dir>/sbin\"."
    exit 1
fi

if [ ! -f "$source_nginx_binary" ]; then
    echo "The source Nginx binary file is not in $source_nginx_dir/sbin."
    echo "Usage: $0 <source_nginx_install_dir>"
    echo "Notice: This script only supports the source Nginx binary stored in \"<source_nginx_install_dir>/sbin\"."
    exit 1
fi

# Step 1: Create a temporary directory and copy the Nginx installation directory.
target_nginx_dir="$(dirname "$source_nginx_tmp")"
mkdir -p "$target_nginx_dir"
echo "Copying $source_nginx_dir to $target_nginx_dir ..."
if ! cp -rp "$source_nginx_dir" "$target_nginx_dir"; then
     echo "Failed to copy the Nginx installation directory"
     exit 1
fi
# Create a directory and compress the components outside the package.
source_related_dir="$source_nginx_tmp/sbin/source_related"
mkdir -p "$source_related_dir"
mkdir -p "$source_related_dir/external_confs"
external_confs_record="$source_related_dir/external_confs/external_conf_record.txt"
touch "${external_confs_record}"
chmod 600 "${external_confs_record}"

# Step 2: Obtain and copy the dependency files specified in compilation options.
echo -e "\e[1;32m Getting installation configure command paths...\e[0m"
keywords="sbin-path|conf-path|error-log-path|http-log-path|http-client-body-temp-path|http-fastcgi-temp-path|http-proxy-temp-path|http-scgi-temp-path|http-uwsgi-temp-path|pid-path|lock-path"
cd "$source_nginx_dir"
strings "$source_nginx_binary" | grep "configure arguments"
strings "$source_nginx_binary" | grep "configure arguments" | grep -Eo "($keywords)=[^[:space:]]+" | awk -F '=' '{print $2}' | while read -r path; do
     # For dependency files already in the package, skip the copy operation.
     if [[ "$path" == "$source_nginx_dir"* ]]; then
         echo "Skip copying $path because it is in the source Nginx directory."
         continue
     fi

     source_path="$path"

     # Obtain the real path of the relative path.
     if [[ "$path" == ../* ]]; then
         source_path=$(realpath --relative-base="$source_nginx_dir" -m "$path")
     fi

     # For Nginx configuration and log files, copy the directory where the files are located.
     if [[ "$source_path" =~ \.conf$ ]] || [[ "$source_path" =~ \.log$ ]]; then
         source_path=$(dirname "$source_path")
     fi

     target_dir="$source_related_dir/$(dirname "$source_path")"
     if [ ! -d "$target_dir" ]; then
         mkdir -p "$target_dir"
     fi
     echo "Copying $source_path to $target_dir ..."
     if ! cp -rp "$source_path" "$target_dir"; then
         echo "Failed to copy file/directory: $source_path"
     fi
 done

# Step 3: Obtain and copy the startup configuration file.
echo " "
echo -e "\e[1;32m Getting startup config file...\e[0m"
ps -ef | grep nginx
nginx_process_info=$(ps -ef | grep nginx)
if grep -q " -c " <<< "$nginx_process_info" || [ -f "$source_nginx_binary" ]; then
    keywords=""
else
  echo -e "\e[1;93m Please refer to the process information of 'ps -ef | grep nginx' above, check whether the source nginx to be migrated is started with a specified configuration file. \e[0m"
  echo -e "\e[1;93m e.g., nginx: master process {path to the nginx binary to be migrated} -c {configuration file path} \e[0m"
  echo -e "\e[1;93m If it is not started based on the specified configuration file, press Enter to skip this step. Otherwise, enter the Nginx binary file path. \e[0m"
  echo "Enter Nginx binary path: "
  read -r nginx_binary_path
  keywords="$nginx_binary_path"
fi
ps -ef | grep nginx | grep -oE "nginx: master process $keywords \-c ([^ ]+)" | while read -r line; do
     CONF_FILE=$(echo "$line" | grep -oE 'c ([^ ]+)' | cut -d ' ' -f2)
     echo "[Startup config file]: $CONF_FILE"
     if [ ! -f "$CONF_FILE" ]; then
         continue
     fi
     conf_dir=$(dirname "$CONF_FILE")
     # If the file is already in the package, skip this step.
     if [[ "$conf_dir" == "$source_nginx_dir"* ]]; then
         continue
     fi

     echo "$CONF_FILE" >> "$external_confs_record"

     target_dir=$(dirname "$source_related_dir$conf_dir")
     if [ ! -d "$target_dir" ]; then
         mkdir -p "$target_dir"
     fi
     echo "Copying $conf_dir to $target_dir ..."
     if ! cp -rp "$conf_dir" "$target_dir"; then
         echo "Failed to copy confs dir: $conf_dir"
     fi
 done

# Step 4: Scan and copy the external files and directories referenced in the configuration file.
echo " "
echo -e "\e[1;32m Scanning included sources in config file...\e[0m"
conf_file_list=()
while IFS= read -r -d '' file; do
     conf_file_list+=("$file")
done < <(find "$source_nginx_tmp" -type f -name "*.conf" -print0)

# Input parameter: [line][relative_base_path]
function handle_included() {
     line="$1"
     relative_base_path="$2"
     path=$(echo "$line" | awk '{print $2}' | sed 's/[";]//g')

     if [[ "$path" == /* ]]; then
         source_path="$path"
         target_path="$source_related_dir$source_path"
     elif [[ "$path" == ../* ]]; then
         source_path=$(realpath --relative-base="$relative_base_path" -m "$path")
         target_path="$source_related_dir$source_path"
     else
         return
     fi

     if [[ "${path##*/}" == \** ]]; then
         source_path=$(dirname "$source_path")
         target_path=$(dirname "$target_path")
     fi

     target_dir=$(dirname "$target_path")
     mkdir -p "$target_dir"
     echo "Copying $source_path to $target_dir ..."
     if ! cp -rp "$source_path" "$target_dir"; then
         echo "Failed to copy file/directory: $path"
     fi
}

for file in "${conf_file_list[@]}"; do
     echo "[conf file]: $file"
     file_dir=$(dirname "$file")
     if [ ! -f "$file" ]; then
         continue
     fi
     # Obtain the directory of the source configuration file.
     if echo "$file" | grep -q "source_related"; then
         source_conf_dir=$(echo "$file_dir" | awk -F 'source_related' '{print $2}')
     else
         source_conf_dir="$source_nginx_dir/conf"
     fi
     # Configuration file directory
     keywords="include|ssl_certificate|ssl_certificate_key|ssl_dhparam"
     cd "$source_conf_dir"
     grep -wE "^[[:space:]]*($keywords)" "$file" | while read -r line; do
         handle_included "$line" "$source_conf_dir"
     done
     # Relative installation path
     keywords="error_log|access_log|root|alias|client_body_temp_path|fastcgi_temp_path|proxy_temp_path|proxy_cache_path|scgi_temp_path|uwsgi_temp_path"
     cd "$source_nginx_dir"
     grep -wE "^[[:space:]]*($keywords)" "$file" | while read -r line; do
         handle_included "$line" "$source_nginx_dir"
     done
 done

# Step 5: In the source_related directory, clear the source Nginx installation directory copied in step 3.
echo " "
cd "$(dirname "$temp_dir")"
source_related_nginx="$source_related_dir$source_nginx_dir"
if [ -d "$source_related_nginx" ]; then
     echo "[remove]: $source_related_nginx"
     rm -rf "${source_related_nginx}"
fi

# Step 6: Package the source component directory.
echo " "
echo -e "\e[1;32m Packing tar...\e[0m"
tar cvf "$migration_tar" "$(basename "$temp_dir")" >/dev/null
if [[ "$?" -ne "${SUCCESS}" ]]; then
     echo "Failed to create tar."
     exit 1
fi

echo "Nginx related components are packaged into $migration_tar."
echo "Note: Please manually check and remove unrelated files/dirs if needed."
echo "Please manually upload it to the node server and extract it using the command: tar xvf $migration_tar -C /custom_path"