为什么在远程机器上执行的 *.sh 脚本有时 return 只输出部分?
Why does a *.sh script executed on a remote machine sometimes return only partial output?
我运行一个命令cat getStorage.sh | ssh -T remoteHost >> storageLog.csv
。
getStorage.sh
看起来像这样:
#! /bin/bash
dateTime=$(date)
echo -n $dateTime,
df -h /directory/ | tail -n 1 | awk '{ print "," }'
通常这个 returns storageLog.csv
看起来像这样:
Tue Sep 7 14:44:59 EDT 2021,275G,500G
然而,有时(偶尔),它 returns 只是部分输出,如下所示:
Tue Sep 7 14:54:59 EDT 2021,
这可能是什么原因造成的?
如果你想整行写或者根本不写,不要打散你的写;如果 df
、tail
或 awk
报告失败,告诉脚本退出后,只做一个 echo
一次写入所有输出。
这既避免了在文件写入一半时尝试读取文件的竞争条件,也避免了写入日期成功但在 df
管道发生之前其他事情失败的错误情况。
每个 write()
系统调用都是原子的(有点——他们 可以 写入比请求更少的字节,但这通常只发生在套接字和其他“受流程影响的对象”上control”,引用 write
的 MacOS 手册页;对于常规文件,当写入的内容少于一页时,写入通常作为一个整体进行或根本不进行——因此您减少了空间当您一次写入一个块的内容时出错,尤其是 当您的文件以 O_APPEND
模式打开时)。
#!/bin/bash
set -o pipefail # tell bash to call a whole pipeline a failure if any part fails
dateTime=$(date) || exit
dfData=$(df -h /directory/ | tail -n 1 | awk '{ print "," }') || exit
echo "$dateTime,$dfData"
我运行一个命令cat getStorage.sh | ssh -T remoteHost >> storageLog.csv
。
getStorage.sh
看起来像这样:
#! /bin/bash
dateTime=$(date)
echo -n $dateTime,
df -h /directory/ | tail -n 1 | awk '{ print "," }'
通常这个 returns storageLog.csv
看起来像这样:
Tue Sep 7 14:44:59 EDT 2021,275G,500G
然而,有时(偶尔),它 returns 只是部分输出,如下所示:
Tue Sep 7 14:54:59 EDT 2021,
这可能是什么原因造成的?
如果你想整行写或者根本不写,不要打散你的写;如果 df
、tail
或 awk
报告失败,告诉脚本退出后,只做一个 echo
一次写入所有输出。
这既避免了在文件写入一半时尝试读取文件的竞争条件,也避免了写入日期成功但在 df
管道发生之前其他事情失败的错误情况。
每个 write()
系统调用都是原子的(有点——他们 可以 写入比请求更少的字节,但这通常只发生在套接字和其他“受流程影响的对象”上control”,引用 write
的 MacOS 手册页;对于常规文件,当写入的内容少于一页时,写入通常作为一个整体进行或根本不进行——因此您减少了空间当您一次写入一个块的内容时出错,尤其是 当您的文件以 O_APPEND
模式打开时)。
#!/bin/bash
set -o pipefail # tell bash to call a whole pipeline a failure if any part fails
dateTime=$(date) || exit
dfData=$(df -h /directory/ | tail -n 1 | awk '{ print "," }') || exit
echo "$dateTime,$dfData"