防止 shell 脚本挂在一行

防止 shell 脚本挂在一行

我编写了一个 shell 脚本,可以帮助我使用 计算远程服务器中的磁盘利用率df -h。我包括下面的代码片段

s_arch_1_per=`sshpass -p 'password' ssh root@server_ip_1 "df -h | grep '/Archive_1'| awk '{print $ (NF-1)}'"`

master_per=`sshpass -p 'password' ssh nidhal@server_ip_2 "df -h | grep '/dev/mapper/centos-root'| awk '{print $ (NF-1)}'"`

arch_5_per=`df -h | grep '/archive_1'| awk '{print $ (NF-1)}'`

df -h问题是在本地或远程系统中,有时由于安装点损坏而挂起执行,从而阻止我的整个 shell 完全执行。当我的脚本df -h在其中一个系统中不起作用时,如何防止我的脚本卡在一行?如果该行执行时间太长,我希望我的脚本跳过一行并继续执行下一行。

答案1

不要将df的输出通过管道传输到grep(这会导致df查询所有已安装的文件系统,甚至是那些没有响应的文件系统 - 例如挂起的 NFS 安装),而是将df您想要的信息作为参数提供给文件系统。

例如,而不是:

df -h | grep '/Archive_1

使用:

df -h /Archive_1

现在df仅尝试获取有关/Archive_1安装点的信息。您可以使用设备节点或安装点作为参数。

使用 GNU df,--output如果您想要的只是大小,您还可以使用该选项...所以您不需要使用 awk (使用 sed 或其他东西删除第一行,即标题仍然有用,因为 GNU df 没有没有抑制标头输出的选项)。例如

df -h --output=size /Archive_1 | sed 1d

另外,您不应该使用反引号命令替换。它们已经过时且已被弃用。代替使用$()

总而言之,那就是这样的:

s_arch_1_per=$(sshpass -p 'password' ssh root@server_ip_1 \
                 'df -h --output=size /Archive_1 | sed 1d')

最后,您应该使用基于密钥的 ssh 身份验证,而不是密码身份验证。但这是另一个问题的答案。


顺便说一句,如果您仍然想要/需要使用 awk,则需要将$字段编号之前的任何符号转义为\$ 如果它在双引号内。例如,\$(NF-1)而不只是$(NF-1).

Shell 的引用是 PITA,当您需要进行多个级别的引用时更是如此 - 例如,当您通过 ssh 将引用的 awk 脚本发送到远程主机时。

为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?有关 shell 引用的各种有用信息和技巧。

相关内容