如何在使用 'while read' 时正确格式化传递给远程服务器的 'if' 语句?
How to properly format an 'if' statement being passed to a remote server in a when using 'while read'?
Ubuntu 18
Bash4.4.0
我想通过 if 语句来查看目录是否存在。如果是这样,我想要一些命令,然后是一个文件。我已经通读了类似的帖子,但 shellcheck 抱怨我的格式。
脚本:
#!/bin/bash
testing="yes"
scriptDir="/root/.work"
wDir="${scriptDir}/.nginx-fix"
if [ "$testing" = "no" ]; then
hostfile="${scriptDir}/.zzz-hostnames"
else
hostfile="${scriptDir}/.zzz-hostnames-tester"
fi
cd "$wDir"
while read fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
< /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
< /dev/null ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
< /dev/null scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
< /dev/null ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
< /dev/null ssh -p 34499 root@"${fqdn}" 'nginx -t'
else
exit 1;
fi
done<"${hostfile}"
Shellcheck 投诉:
root@me ~/.work/.nginx-fix # shellcheck .nginx-fixer.sh
In .nginx-fixer.sh line 13:
while read fqdn; do
^-- SC1073: Couldn't parse this while loop.
^-- SC1061: Couldn't find 'done' for this 'do'.
In .nginx-fixer.sh line 15:
< /dev/null if ssh -p 33899 root@"${fqdn}" '[ -d /etc/nginx ]'; then
^-- SC1062: Expected 'done' matching previously mentioned 'do'.
^-- SC1072: Expected "#". Fix any mentioned problems and try again.
我很感激你的想法。
运行 通过 'bash -n' 的脚本将指示 'real' 错误:
bash -n x.sh
x.sh: line 15: syntax error near unexpected token `then'
x.sh: line 15: ` < /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'
您不能在 'if' 语句之前放置重定向。将重定向移动到 'ssh'(if 的条件部分)命令,例如:
# USE:
if ssh < /dev/null -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'
# AND NOT:
< /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'
您可以将脚本重构为更清晰的版本并删除所有 </dev/null
:
while read -r fqdn; do {
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root@"${fqdn}" 'nginx -t'
else
exit 1;
fi
} </dev/null; done < "${hostfile}"
几乎肉眼看不见,我把do ... done
里面的命令都放在{ .. } </dev/null
里面了。这样任何命令都不会从 ${hostfile}
读取并且不会与 while read
.
混淆
另一种选择是使用专用文件描述符并将其编号传递给读取:
while read -r -u 10 fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root@"${fqdn}" 'nginx -t'
else
exit 1;
fi
done 10<"${hostfile}"
Ubuntu 18
Bash4.4.0
我想通过 if 语句来查看目录是否存在。如果是这样,我想要一些命令,然后是一个文件。我已经通读了类似的帖子,但 shellcheck 抱怨我的格式。
脚本:
#!/bin/bash
testing="yes"
scriptDir="/root/.work"
wDir="${scriptDir}/.nginx-fix"
if [ "$testing" = "no" ]; then
hostfile="${scriptDir}/.zzz-hostnames"
else
hostfile="${scriptDir}/.zzz-hostnames-tester"
fi
cd "$wDir"
while read fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
< /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
< /dev/null ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
< /dev/null scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
< /dev/null ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
< /dev/null ssh -p 34499 root@"${fqdn}" 'nginx -t'
else
exit 1;
fi
done<"${hostfile}"
Shellcheck 投诉:
root@me ~/.work/.nginx-fix # shellcheck .nginx-fixer.sh
In .nginx-fixer.sh line 13:
while read fqdn; do
^-- SC1073: Couldn't parse this while loop.
^-- SC1061: Couldn't find 'done' for this 'do'.
In .nginx-fixer.sh line 15:
< /dev/null if ssh -p 33899 root@"${fqdn}" '[ -d /etc/nginx ]'; then
^-- SC1062: Expected 'done' matching previously mentioned 'do'.
^-- SC1072: Expected "#". Fix any mentioned problems and try again.
我很感激你的想法。
运行 通过 'bash -n' 的脚本将指示 'real' 错误:
bash -n x.sh
x.sh: line 15: syntax error near unexpected token `then'
x.sh: line 15: ` < /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'
您不能在 'if' 语句之前放置重定向。将重定向移动到 'ssh'(if 的条件部分)命令,例如:
# USE:
if ssh < /dev/null -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'
# AND NOT:
< /dev/null if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]' ; then'
您可以将脚本重构为更清晰的版本并删除所有 </dev/null
:
while read -r fqdn; do {
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root@"${fqdn}" 'nginx -t'
else
exit 1;
fi
} </dev/null; done < "${hostfile}"
几乎肉眼看不见,我把do ... done
里面的命令都放在{ .. } </dev/null
里面了。这样任何命令都不会从 ${hostfile}
读取并且不会与 while read
.
另一种选择是使用专用文件描述符并将其编号传递给读取:
while read -r -u 10 fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root@"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root@"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root@"${fqdn}":/etc/nginx
ssh -p 34499 root@"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root@"${fqdn}" 'nginx -t'
else
exit 1;
fi
done 10<"${hostfile}"