我正在使用 sh 脚本进行 Docker 容器构建和运行,我想向 cli 添加心跳检测命令,但是当我使用变量拼接它时,它无法正确识别它,但我通过 echo 输出的 cli 命令启动正常。
这是脚本代码
# Heartbeat URL
health_check_cmd="curl -f http://172.17.0.1:5110/v2/alarm/hostRecord/find || exit 1"
# Heartbeat check interval, default: 30 seconds
health_check_interval=30s
dockerContainerOpe(){
echo 'Starting operations on Docker container'
# Stop and remove container
if docker ps -a --format '{{.Names}}' | grep -q "^$container_name\$"; then
docker rm -f $container_name
fi
# Build container
docker build -t $docker_version_name --build-arg jarName=$jar_name .
# Prepare docker run command
run_cmd="docker run -itd $port_args --name=$container_name -v $docker_volume_path"
# Add health check command and interval
if [[ -n "$health_check_cmd" ]]; then
run_cmd="$run_cmd --health-cmd=\"$health_check_cmd\" --health-interval=$health_check_interval"
fi
# Add other parameters
run_cmd="$run_cmd --restart=always --privileged=true $docker_version_name"
echo "Running command: $run_cmd"
$run_cmd
# Remove dangling containers
if [[ -n $(docker images | grep "none" | awk '{print $3}') ]]; then
docker rmi $(docker images | grep "none" | awk '{print $3}')
fi
}
运行命令:
docker run -itd -p 5150:5150 --name=cmmop-alarm -v /home/logs:/home/logs --health-cmd="curl -f http://172.17.0.1:5110/v2/alarm/hostRecord/find ||出口1” --health-interval=30s --restart=always --privileged=true cmmop-alarm:1.0.0
未知的简写标志:-f 中的“f”
请参阅“docker run --help”。
docker
Server Version: 20.10.17
Operating System: CentOS Linux 7 (Core)
我做错了什么?
您尝试构建命令行的方式不起作用。考虑以下命令:
touch "this is" "a test"
从 shell 提示符运行此命令,它将创建两个文件,名为
this is
和 a test
。如果我尝试像您在脚本中所做的那样构建命令:
run_cmd="touch \"this is\" \"a test\"""
然后运行变量:
$run_cmd
我最终会得到:
$ ls -1
'"a'
'is"'
'test"'
'"this'
当您像这样使用变量时,shell 不会“看到”变量中包含的引号;它们被简单地视为任何相邻单词的一部分,并且任何空格都被视为参数分隔符。
有几种方法可以解决这个问题。一是使用
eval
命令:
eval "$run_cmd"
这正是我们想要的。或者,如果您使用的是 Bash,则可以使用数组来构建命令行:
run_cmd=(touch "this is" "a test")
"${run_cmd[@]}"
我们可以使用该技术重写您的 shell 脚本,如下所示:
#!/bin/bash
# Heartbeat URL
health_check_cmd="curl -f http://172.17.0.1:5110/v2/alarm/hostRecord/find || exit 1"
# Heartbeat check interval, default: 30 seconds
health_check_interval=30s
# I added some default values in order to test the script locally
jar_name=myproject.jar
docker_version_name=example:latest
container_name=example
port_args="9090:8080"
docker_volume_path="$PWD:/src"
dockerContainerOpe() {
echo 'Starting operations on Docker container'
# Stop and remove existing container
docker container inspect "$container_name" 2>/dev/null &&
docker container rm -f "$container_name"
# Build container
docker build -t "$docker_version_name" --build-arg "jarName=$jar_name" .
# Prepare docker run command
run_cmd=(
docker run -d -p "$port_args"
"--name" "$container_name" -v "$docker_volume_path"
--restart=always --privileged=true
)
# Add health check command and interval
if [[ -n "$health_check_cmd" ]]; then
run_cmd+=(--health-cmd "$health_check_cmd" --health-interval "$health_check_interval")
fi
# Add other parameters
run_cmd+=("$docker_version_name")
echo "Running command: ${run_cmd[*]}"
"${run_cmd[@]}"
}
dockerContainerOpe