我要评分
获取效率
正确性
完整性
易理解

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 leakage. You can copy some or all content of the script as required.
  • This script supports only Nginx that is compiled from the source code with its binary file stored in the Nginx_installation_path/sbin directory.
  • If Nginx is installed using an RPM package, it cannot be migrated by manually adding components. To migrate Nginx in this case, you can select the VM image migration method or manually migrate it.
  1. Create a script (pack_nginx_sources.sh for example) in any location of the source VM and add content of pack_nginx_sources.sh to the script. (The script is an example and can be customed.)
  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
    

    Enter the Nginx binary path as prompted.

    1
    Enter nginx binary path:
    
    • /path/to: path to the script.
    • /usr/local/nginx: absolute path to the source Nginx installation directory. Replace it with the actual one.
  3. If the following error information is displayed during script execution, perform the following operations:
    -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
  4. After the packaging is complete, delete the /home/nginx_mig_tmp directory.

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
#!/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...\n \e[0m"
ps -ef | grep nginx
echo " "
echo "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."
echo "e.g., nginx: master process {path to the Nginx binary to be migrated} -c {configuration file path}"
echo "If it is not specified directly, press Enter to skip this step; otherwise, please enter the configuration file path."
echo "Enter Nginx binary path: "
read -r nginx_binary_path
 keywords="$nginx_binary_path"
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"