我有这样一个命令,它可以告诉我系统是否有磁盘已满(>=70%已满):
if [[ -n df -PTh|column -t|awk '{print $6 $7}'|awk -F"%" '{printf "%-9s %-5s\n",$1,$2}'|grep -v -e "Use" -e "Mounted"|awk '$1>70{printf "%-9s %-5s\n",$1,$2}' ]]; then echo "not present"; else echo ">70 is present"; fi
我想使用 SSH 在远程服务器上执行上述命令。例如:
ssh remoteserver "if [[ -n df -PTh|column -t|awk '{print $6 $7}'|awk -F"%" '{printf "%-9s %-5s\n",$1,$2}'|grep -v -e "Use" -e "Mounted"|awk '$1>70{printf "%-9s %-5s\n",$1,$2}' ]]; then echo "not present"; else echo ">70 is present"; fi"
但是当我尝试这样做时,出现了以下错误:
HOST: remoteserver bash: -c: line 0: syntax error in conditional expression bash: -c: line 0: syntax error near /home'
bash: -c: line 0:if [[ -n 92 /home'
答案1
首先,我将 awk/grep/awk/grep/awk/grep/etc 语句的战争罪行简化为:
df | awk '$5~/([7-9]|10)[0-9]/'
它能完成检查输出所需的所有工作。您可以{print ...}
在语句中添加一个子句,awk
如果您真的需要漂亮的输出,但考虑到你只是检查一下如果有输出,我们合理点处理这件事☺。
我们还可以缩短 if/else。我还更正了方向——你的方向是相反的。整个命令现在看起来像:
[[ -n $(df | awk '$5~/([7-9]|10)[0-9]/') ]] && echo 'ACHTUNG!' || echo 'No >=70s'
我想你会同意这只是轻微地更有启发。
现在你可能可以手动将其转义并将其包装起来,bash -c "..."
但这样做有什么乐趣呢?相反,让我们将命令保存到本地文件(例如commands.txt)中,你可以像这样将其发送到服务器:
ssh user@host $(<commands.txt)
你可以把它留在那里。你实际上可以将原始命令的工作版本放入其中并将其发送过去。这个东西非常强大……但我们不想这样做……当我们可以更聪明(和欺骗性地)使用命令并取消 if 括号(这是导致转义问题的原因)时,我们不想这样做。
我们目前正在df
远程运行并远程处理它。我们不需要这样做。我们可以让它ssh
运行df
,然后在本地处理输出。这立即解决了转义问题,但我们目前被逻辑[[
括号束缚着]]
,这会让重写有点难看:
[[ -n $(ssh user@host df | awk '$5~/([7-9]|10)[0-9]/') ]] && .......
真恶心。
我们比那更好。
与在我们之前走过的猴子和猿猴不同,我们有退出代码。
当某些程序运行完毕时,它会返回一个代码。这些代码表示各种各样的东西但一般来说,0
意思是“我完全按照我的设计去做了”,而任何更高级别的表达都意味着“我做得不好,Bawss”。
条件钩子&&
会||
根据输入的退出代码来决定是否运行。在我们的例子中,这意味着如果我们awk
以非零方式退出,我们就可以控制代码流:
ssh user@host df | awk '$5~/([7-9]|10)[0-9]/ {exit 1}' && echo 'No >=70s' || echo 'ACHTUNG!'
这也意味着它会在检测到第一个 >=70 的值时立即退出。如果你有数百万个驱动器,这可以为你节省秒优于其他领先品牌的脚本。所以是的,只是为了重申这个最终版本中发生的事情:
- 我们正在连接服务器并
df
远程运行 - 输出通过管道传输回本地实例
awk
awk
查看第五列是否与正则表达式匹配以匹配 70-100- 如果是,则退出代码 1,并
||
执行代码(那里是驱动器使用率超过 70%) - 如果没有,它将退出代码 0 并
&&
执行代码。
在之前的修订中,我也NR>1
对awk
语句进行了检查,但考虑到我们明确检查了第五列的值(并且它必须是一个数字才能工作),我们也可以放心地省略它。