Rate This Document
Findability
Accuracy
Completeness
Readability

Packaging Script

In the actual Redis migration scenario, some configuration and data files are stored outside the Redis installation path. To facilitate source component packaging, a packaging script is provided for reference. The script packages the source components stored outside the Redis installation path to the /Packaging_path/Redis_installation_path/bin (or src)/source_related directory according to the original directory structure.

The tool cannot automatically migrate Redis installed using an RPM package. Perform a manual migration instead.

Prerequisites

Before packaging, you need to start the Redis instance. If a sentinel node is used, ensure that the sentinel node is started together.

Procedure

  1. Create an .sh script file (for example, pack_redis_sources.sh) in any directory on the source VM. For details about the script content, see pack_redis_sources.sh.
  2. After starting Redis, run the script to start packaging. Replace /path/to with the actual script path.
    bash /path/to/pack_redis_sources.sh

    If a password is configured for Redis, enter the password (which can be found in the requirepass field in the Redis configuration file). Then the script automatically starts packaging. You can obtain the compressed installation package according to the output.

    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:
    1
    -bash: ./pack_redis_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_redis_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.
    1
    sed -i 's/\r//g' pack_redis_sources.sh
    
  3. After the packaging is complete, delete the source_related directory and devkit_redis_conf_data.json file.
  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 redis.tar.gz
        
      4. After the decompression is complete, you can run the following command to delete the source component package.
        1
        rm -f redis.tar.gz
        
      5. Set the path to the decompressed file as the source component path.

pack_redis_sources.sh

The script automatically identifies the IP address and port of Redis (and those of the sentinel node if involved). You can customize the content as required.

  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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
#!/bin/bash
 
# Check whether Redis is started.
redis_pid=$(pgrep -f redis-server)
if [ -z "$redis_pid" ]; then
    echo "The Redis service is not running. The script exits."
    exit 1
else
    echo "The Redis service is running. PID: $redis_pid"
fi
 
# Check whether the Redis sentinel is started.
sentinel_pid=$(pgrep -f redis-sentinel)
if [ -z "$sentinel_pid" ]; then
    echo "The Redis sentinel is not running."
    is_sentinel_mode=false
else
    echo "The Redis sentinel is running. PID: $sentinel_pid"
    is_sentinel_mode=true
fi
 
# Obtain the IP address and port of the Redis service.
# Run the ps command to obtain information about redis-server and redis-sentinel.
redis_info=$(ps -ef | grep redis | grep -v grep)
 
# Get the IP address and port of redis-server.
redis_server_info=$(echo "$redis_info" | grep 'redis-server' | awk '{print $NF}')
redis_host=$(echo "$redis_server_info" | cut -d ':' -f1)
redis_port=$(echo "$redis_server_info" | cut -d ':' -f2)
 
# If the IP address and port of Redis are not obtained, use the default values.
if [ -z "$redis_host" ]; then
    redis_host="127.0.0.1"
    redis_port="6379"
    echo "Failed to obtain the IP address and port of redis-server. Use the default values: $redis_host:$redis_port"
else
    echo "Obtained the IP address and port of redis-server: $redis_host:$redis_port"
fi
 
# Obtain the IP address and port of redis-sentinel (if any).
redis_sentinel_host="127.0.0.1"
redis_sentinel_port="26379"
sentinel_info=$(echo "$redis_info" | grep 'redis-sentinel')
 
if [ -n "$sentinel_info" ]; then
    # Use a regular expression to match and extract the IP address and port.
    sentinel_info=$(echo "$sentinel_info" | grep -oP '\d+\.\d+\.\d+\.\d+:\d+|\*:\d+')  # Extract information similar to *:26379 or IP_address:port.
 
    # Extract the IP address and port.
    sentinel_host=$(echo "$sentinel_info" | cut -d ':' -f1)
    sentinel_port=$(echo "$sentinel_info" | cut -d ':' -f2)
 
    # If the IP address is * or not set, use the default value.
    if [ "$sentinel_host" == "*" ] || [ -z "$sentinel_host" ]; then
        sentinel_host="127.0.0.1"
        echo "The IP address of redis-sentinel is set to the default value: $sentinel_host"
    fi
 
    # If the port is * or not set, use the default value.
    if [ -z "$sentinel_port" ] || [ "$sentinel_port" == "*" ]; then
        sentinel_port="26379"
        echo "The port of redis-sentinel is set to the default value: $sentinel_port"
    fi
    redis_sentinel_host=$sentinel_host
    redis_sentinel_port=$sentinel_port
 
    echo "Obtained the IP address and port of redis-sentinel: $redis_sentinel_host:$redis_sentinel_port"
else
    echo "Failed to obtain redis-sentinel information. Use the default values: $redis_sentinel_host:$redis_sentinel_port"
fi
 
# Obtain the path to the redis-server executable file.
redis_exe_path=$(readlink -f /proc/$redis_pid/exe)
 
# Obtain the path to the parent directory.
redis_parent_dir=$(dirname "$redis_exe_path")
 
# Remove the slash (if any) at the end of the path.
redis_parent_dir=$(echo "$redis_parent_dir" | sed 's/\/$//')
 
# Check whether the parent directory of redis-server is the src or bin installation directory.
if [[ "$redis_parent_dir" == */src ]]; then
    installation_dir=$(dirname "$redis_parent_dir")
    echo "src installation directory identified: $installation_dir"
elif [[ "$redis_parent_dir" == */bin ]]; then
    installation_dir="$redis_parent_dir"
    echo "bin installation directory identified: $installation_dir"
 
    # Check whether the parent directory of bin contains src/redis-server.
    parent_dir=$(dirname "$redis_parent_dir")
    if [ -f "$parent_dir/src/redis-server" ]; then
        # Set installation_dir to $parent_dir (src directory).
        installation_dir="$parent_dir"
        redis_parent_dir="$parent_dir/src"  # Update redis_parent_dir to src.
        echo "Installation directory: $installation_dir"
    else
        echo "$parent_dir does not contain src/redis-server. Use bin as the installation directory."
        installation_dir="$redis_parent_dir"
    fi
else
    echo "The given directory is neither the src directory nor the bin directory. Check whether the path is correct."
    exit 1
fi
 
# Obtain the IP address inputted by the user. The default value is $redis_host.
read -p "The identified IP address of the Redis server is $redis_host. To change the IP address, input the correct one. To use the identified IP address, press Enter: " redis_host_input
redis_host=${redis_host_input:-$redis_host}
 
# Obtain the port inputted by the user. The default value is $redis_port.
read -p "The identified port of the Redis server is $redis_port. To change the port, input the correct one. To use the identified port, press Enter: " redis_port_input
redis_port=${redis_port_input:-$redis_port}
 
# Obtain the password inputted by the user. By default, the password is empty.
read -s -p "Input the password of the Redis server (If no password is configured, press Enter): " redis_password
echo
redis_password=${redis_password:-""}
 
if [ -n "$sentinel_info" ]; then
    # Ask the user to change the IP address and port of the Redis sentinel.
    read -p "The identified IP address of the Redis sentinel is $redis_sentinel_host. To change the IP address, input the correct one. To use the identified IP address, press Enter: " redis_sentinel_host_input
    redis_sentinel_host=${redis_sentinel_host_input:-$redis_sentinel_host}
 
    read -p "The identified port of the Redis sentinel is $redis_sentinel_port. To change the port, input the correct one. To use the identified port, press Enter: " redis_sentinel_port_input
    redis_sentinel_port=${redis_sentinel_port_input:-$redis_sentinel_port}
else
    echo "Your current server does not start the sentinel node."
fi
 
# You can check the formats of the inputted IP address and port, for example, using a regular expression.
# Check the IP address format.
if [[ ! "$redis_host" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Error: Invalid Redis server IP address format!"
    exit 1
fi
 
# Check whether the port is valid.
if [[ ! "$redis_port" =~ ^[0-9]+$ ]]; then
    echo "Error: Invalid Redis server port!"
    exit 1
fi
 
# Check the format of the Redis sentinel IP address.
if [[ ! "$redis_sentinel_host" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Error: Invalid Redis sentinel IP address format!"
    exit 1
fi
 
# Check whether the port of the Redis sentinel is valid.
if [[ ! "$redis_sentinel_port" =~ ^[0-9]+$ ]]; then
    echo "Error: Invalid Redis sentinel port!"
    exit 1
fi
 
# Switch to the Redis installation directory and ensure that redis-cli can run properly.
cd "$redis_parent_dir"
echo "Go to the installation directory: $redis_parent_dir"
 
# Obtain the Redis configuration file path.
echo "Obtaining the Redis configuration file path..."
if [ -z "$redis_password" ]; then
    config_file_path=$(./redis-cli -h "$redis_host" -p "$redis_port" INFO | grep config_file | cut -d ':' -f2 | tr -d '[:space:]')
else
    config_file_path=$(./redis-cli -h "$redis_host" -p "$redis_port" -a "$redis_password" INFO | grep config_file | cut -d ':' -f2 | tr -d '[:space:]')
fi
 
if [ -z "$config_file_path" ]; then
    echo "Failed to obtain the Redis configuration file path. Check that the Redis service is started and the password is correct."
    exit 1
fi
config_file_path=$(realpath "$config_file_path")
 
echo "Configuration file path: '$config_file_path'"
 
# Obtain the path to the configuration file in the installation directory.
if [[ "$config_file_path" == "$installation_dir"* ]]; then
    redis_conf_in_package=true
    echo "The configuration file is in the installation directory. Skip the step of copying the configuration file."
else
    redis_conf_in_package=false
    echo "The configuration file is not in the installation directory. Copying the configuration file..."
    
    # Obtain the absolute path to the parent directory of the configuration file.
    config_file_parent_dir=$(dirname "$config_file_path")
    
    # Construct the target directory, which is source_related+parent directory of the configuration file under redis_parent_dir.
    target_dir="$redis_parent_dir/source_related$config_file_parent_dir"
    
    # Create a target directory (if not found).
    mkdir -p "$target_dir"
    cp "$config_file_path" "$target_dir"
    
    echo "The configuration file has been copied to $target_dir."
fi
 
# Obtain the Redis data directory.
echo "Obtaining the Redis data directory..."
if [ -z "$redis_password" ]; then
    redis_data_dir=$(./redis-cli -h "$redis_host" -p "$redis_port" CONFIG GET dir | awk 'NR==2 {print substr($0, index($0,$2))}' | tr -d '"')
else
    redis_data_dir=$(./redis-cli -h "$redis_host" -p "$redis_port" -a "$redis_password" CONFIG GET dir | awk 'NR==2 {print substr($0, index($0,$2))}' | tr -d '"')
fi
 
# Return the original Redis data directory.
 
# Check whether the data directory is set.
if [ -z "$redis_data_dir" ]; then
    echo "The Redis data directory is not set. Check the dir setting in the configuration file."
else
    echo "Redis data directory: $redis_data_dir"
fi
 
# Obtain the values of dbfilename and appendfilename.
echo "Obtaining dbfilename and appendfilename..."
if [ -z "$redis_password" ]; then
    dbfilename=$(./redis-cli -h "$redis_host" -p "$redis_port" CONFIG GET dbfilename | awk 'NR==2 {print substr($0, index($0,$2))}' | tr -d '"')
    appendfilename=$(./redis-cli -h "$redis_host" -p "$redis_port" CONFIG GET appendfilename | awk 'NR==2 {print substr($0, index($0,$2))}' | tr -d '"')
else
    dbfilename=$(./redis-cli -h "$redis_host" -p "$redis_port" -a "$redis_password" CONFIG GET dbfilename | awk 'NR==2 {print substr($0, index($0,$2))}' | tr -d '"')
    appendfilename=$(./redis-cli -h "$redis_host" -p "$redis_port" -a "$redis_password" CONFIG GET appendfilename | awk 'NR==2 {print substr($0, index($0,$2))}' | tr -d '"')
fi
 
echo "dbfilename: $dbfilename"
echo "appendfilename: $appendfilename"
 
# Check Redis data files.
if [ -n "$redis_data_dir" ]; then
 
    # Check whether the Redis data directory is under the installation directory.
    if [[ "$redis_data_dir" != "$installation_dir"* ]]; then
        redis_dir_in_package=false
        echo "The Redis data directory is not under the installation directory. Creating a directory and copying data files..."
 
        # Create a target directory and ensure that its path is complete.
        mkdir -p "$redis_parent_dir/source_related$redis_data_dir"
 
        # Check whether dbfilename is set.
        if [ -n "$dbfilename" ]; then
            if [ -f "$redis_data_dir/$dbfilename" ]; then
                echo "Copying the dbfilename file..."
                cp "$redis_data_dir/$dbfilename" "$redis_parent_dir/source_related$redis_data_dir"
            else
                echo "dbfilename not found: $redis_data_dir/$dbfilename"
            fi
        else
            echo "dbfilename not set. Skip the step of copying the dbfilename file."
        fi
 
        # Check whether appendfilename is set. If not set, use the default value appendonly.aof.
        if [ -z "$appendfilename" ]; then
            appendfilename="appendonly.aof"
            echo "appendfilename not set. The default value $appendfilename is used"
        fi
 
        # Find appendfilename and copy the file.
        if [ -f "$redis_data_dir/$appendfilename" ]; then
            echo "Copying the appendfilename file..."
            cp "$redis_data_dir/$appendfilename" "$redis_parent_dir/source_related$redis_data_dir"
        else
            echo "appendfilename not found: $redis_data_dir/$appendfilename. Skip the copy operation."
        fi
 
        echo "The Redis data files have been copied to $redis_parent_dir/source_related$redis_data_dir."
    else
        redis_dir_in_package=true
        echo "The Redis data directory is under the installation directory. Skip the step of copying data files."
    fi
else
    echo "The Redis data directory is not set. Skip the step of copying data files."
fi
 
# Obtain the logfile configuration.
if [ -z "$redis_password" ]; then
    logfile=$(./redis-cli -h "$redis_host" -p "$redis_port" CONFIG GET logfile | sed -n '2p')
else
    logfile=$(./redis-cli -h "$redis_host" -p "$redis_port" -a "$redis_password" CONFIG GET logfile | sed -n '2p')
fi
 
# Check whether logfile is configured.
if [ -n "$logfile" ]; then
    echo "Log file path: $logfile"
    
    # If the log file is not in the package, copy it.
    if [[ "$logfile" != "$installation_dir"* ]]; then
        redis_logfile_in_package=false
        echo "The log file is not in the installation directory. Copying the log file..."
        mkdir -p "$redis_parent_dir/source_related$(dirname "$logfile")"
        cp "$logfile" "$redis_parent_dir/source_related$logfile"
        echo "The log file has been copied to the target directory: $redis_parent_dir/source_related$logfile"
    else
        redis_logfile_in_package=true
        echo "The log file is in the installation directory. Skip the step of copying the log file."
    fi
else
    echo "The log file path is not set. Skip the step of copying the log file."
fi
 
# Obtain the pidfile configuration.
if [ -z "$redis_password" ]; then
    pidfile=$(./redis-cli -h "$redis_host" -p "$redis_port" CONFIG GET pidfile | sed -n '2p')
else
    pidfile=$(./redis-cli -h "$redis_host" -p "$redis_port" -a "$redis_password" CONFIG GET pidfile | sed -n '2p')
fi
 
# Check whether pidfile is configured.
if [ -n "$pidfile" ]; then
    echo "PID file path: $pidfile"
    # Save only the PID file path.
else
    echo "The PID file path is not set. Skip PID file processing."
fi
 
if [ -n "$sentinel_pid" ]; then
 
    # Obtain the sentinel configuration file path.
    echo "Obtaining the sentinel configuration file path..."
    if [ -z "$redis_password" ]; then
        sentinel_config_file_path=$(./redis-cli -h "$redis_sentinel_host" -p "$redis_sentinel_port" INFO | grep config_file | cut -d ':' -f2 | tr -d '[:space:]')
    else
        sentinel_config_file_path=$(./redis-cli -h "$redis_sentinel_host" -p "$redis_sentinel_port" -a "$redis_password" INFO | grep config_file | cut -d ':' -f2 | tr -d '[:space:]')
    fi
    sentinel_config_file_path=$(realpath "$sentinel_config_file_path")
 
    # Check sentinel_config_file_path.
    if [ -e "$sentinel_config_file_path" ]; then
        echo "Redis sentinel configuration file path: '$sentinel_config_file_path'"
 
        # Obtain the path to the sentinel.conf file in the installation directory.
        if [[ "$sentinel_config_file_path" == "$installation_dir"* ]]; then
            sentinel_conf_in_package=true
            echo "The sentinel configuration file is in the installation directory. Skip the step of copying the configuration file."
            
        else
            sentinel_conf_in_package=false
            echo "The sentinel configuration file is not in the installation directory. Copying the configuration file..."
 
            # Obtain the absolute path to the parent directory of the configuration file.
            config_file_parent_dir=$(dirname "$sentinel_config_file_path")
            
            # Construct the target directory, which is source_related+parent directory of the configuration file under redis_parent_dir.
            target_dir="$redis_parent_dir/source_related$config_file_parent_dir"
            
    # Create a target directory (if not found).
            mkdir -p "$target_dir"
            cp "$sentinel_config_file_path" "$target_dir"
            
            echo "The sentinel configuration file has been copied to $target_dir."
        fi
 
        # Obtain the Redis sentinel data directory (from sentinel.conf).
        sentinel_data_dir=$(grep -i "^dir" "$sentinel_config_file_path" | cut -d ' ' -f2)
        
        # If sentinel_data_dir is ./, leave it empty.
        if [ "$sentinel_data_dir" == "./" ]; then
            sentinel_data_dir=""
            echo "Redis sentinel data directory: $sentinel_data_dir"
        else
            echo "Redis sentinel data directory: $sentinel_data_dir"
        fi
 
    else
        echo "Redis sentinel configuration file path not found. Skip the subsequent operations. Check that the file exists."
    fi
 
else
    echo "Redis sentinel node not detected. Skip configuration file copying and data directory processing."
fi
 
# Create an output file path (with the .json suffix).
output_file="$redis_parent_dir/devkit_redis_conf_data.json"
 
# Obtain Redis and sentinel configurations.
redis_conf="${config_file_path:-}"
redis_dir="${redis_data_dir:-}"
redis_dir_in_package=${redis_dir_in_package:-false}
redis_logfile_in_package=${redis_logfile_in_package:-false}
redis_dbfile="${redis_data_dir}/${dbfilename:-}"
redis_aof="${redis_data_dir}/${appendfilename:-}"
redis_logfile="${logfile:-}"
redis_pidfile="${pidfile:-}"
sentinel_conf="${sentinel_config_file_path:-}"
sentinel_dir="${sentinel_data_dir:-}"
redis_conf_in_package=${redis_conf_in_package:-false}
sentinel_conf_in_package=${sentinel_conf_in_package:-false}
is_sentinel_mode=${is_sentinel_mode:-false}
sentinel_dir=$(echo "$sentinel_dir" | sed 's/^"\(.*\)"$/\1/')
 
# Construct JSON data.
json_data=$(cat <<EOF
{
"redis": {
    "redis_conf": "$redis_conf",
    "redis_conf_in_package": $redis_conf_in_package,
    "redis_dir": "$redis_dir",
    "redis_dir_in_package": $redis_dir_in_package,
    "redis_dbfile": "$redis_dbfile",
    "redis_aof": "$redis_aof",
    "redis_logfile": "$redis_logfile",
    "redis_logfile_in_package": $redis_logfile_in_package,
    "redis_pidfile": "$redis_pidfile"
},
"sentinel": {
    "sentinel_conf": "$sentinel_conf",
    "is_sentinel_mode": $is_sentinel_mode,
    "sentinel_conf_in_package": $sentinel_conf_in_package,
    "sentinel_dir": "$sentinel_dir"
}
}
EOF
)
 
# Write JSON data to a file.
echo "$json_data" > "$output_file"
 
# Output the completion message.
echo "The configuration data has been written into $output_file."
 
# Package the installation directory.
echo "Packaging the installation directory..."
# Switch to the parent directory of installation_dir.
cd "$installation_dir/.." || exit
 
# Generate a TAR package. The package contains the subdirectories of installation_dir, that is, $(basename "$installation_dir").
tar -zcf "redis.tar.gz" "$(basename "$installation_dir")"
 
# Obtain the absolute path to the current working directory (parent directory of installation_dir).
final_tar_path="$(pwd)/redis.tar.gz"
 
# Output the absolute path to the final TAR package after the packaging is complete.
echo "Packaging completed. The installation directory has been packaged to $final_tar_path."