在shell脚本的循环中,我连接到各种服务器并运行一些命令。例如
#!/bin/bash
FILENAME=$1
cat $FILENAME | while read HOST
do
0</dev/null ssh $HOST 'echo password| sudo -S
echo $HOST
echo $?
pwd
echo $?'
done
这里我正在运行“echo $ HOST”和“pwd”命令,我通过“echo $?”获得退出状态。
我的问题是,我希望能够将我在远程运行的命令的退出状态存储在某个变量中,然后(根据命令是否成功),将日志写入本地文件。
感谢任何帮助和代码。
答案 0 :(得分:26)
ssh
将退出远程命令的退出代码。例如:
$ ssh localhost exit 10
$ echo $?
10
因此,在您的ssh
命令退出后,您只需检查$?
即可。您需要确保不屏蔽返回值。例如,您的ssh命令以:
echo $?
这将始终返回0.你可能想要的是更像这样的东西:
while read HOST; do
echo $HOST
if ssh $HOST 'somecommand' < /dev/null; then
echo SUCCESS
else
echo FAIL
done
您也可以这样写:
while read HOST; do
echo $HOST
if ssh $HOST 'somecommand' < /dev/null
if [ $? -eq 0 ]; then
echo SUCCESS
else
echo FAIL
done
答案 1 :(得分:2)
您可以将退出状态分配给变量,只需执行以下操作:
variable=$?
在您尝试检查的命令之后。不要echo $?
之前或$?
的新值将是echo
的退出代码(通常为0)。
答案 2 :(得分:0)
一个有趣的方法是使用反引号检索局部变量中每个ssh命令集的整个输出,或者甚至使用特殊的charachter(为简单起见“:”)分隔:
export MYVAR=`ssh $HOST 'echo -n ${HOSTNAME}\:;pwd'`
在此之后,您可以使用awk
将MYVAR
拆分为结果并继续进行bash测试。
答案 3 :(得分:0)
也许准备另一边的日志文件并将其传递给stdout,如下所示:
ssh -n user@example.com 'x() { local ret; "$@" >&2; ret=$?; echo "[`date +%Y%m%d-%H%M%S` $ret] $*"; return $ret; };
x true
x false
x sh -c "exit 77";' > local-logfile
基本上只是使用此x
包装器为要调用的远程上的所有内容添加前缀。它也适用于条件,因为它不会改变命令的退出代码。
您可以轻松循环此命令。
此示例将日志写入:
[20141218-174611 0] true
[20141218-174611 1] false
[20141218-174611 77] sh -c exit 77
当然,您可以使其更易于解析或使其适应您的日志文件的样子。请注意,远程程序的未捕获的正常stdout
将写入stderr
(请参阅x()
中的重定向)。
如果您需要一个配方来捕获并准备日志文件的命令输出,这里有一个来自https://gist.github.com/hilbix/c53d525f113df77e323d的捕获器的副本 - 但是,这是一个更大的样板来“运行当前的东西shell的上下文,后处理stdout + stderr而不会打扰返回代码“:
# Redirect lines of stdin/stdout to some other function
# outfn and errfn get following arguments
# "cmd args.." "one line full of output"
: catch outfn errfn cmd args..
catch()
{
local ret o1 o2 tmp
tmp=$(mktemp "catch_XXXXXXX.tmp")
mkfifo "$tmp.out"
mkfifo "$tmp.err"
pipestdinto "$1" "${*:3}" <"$tmp.out" &
o1=$!
pipestdinto "$2" "${*:3}" <"$tmp.err" &
o2=$!
"${@:3}" >"$tmp.out" 2>"$tmp.err"
ret=$?
rm -f "$tmp.out" "$tmp.err" "$tmp"
wait $o1
wait $o2
return $ret
}
: pipestdinto cmd args..
pipestdinto()
{
local x
while read -r x; do "$@" "$x" </dev/null; done
}
STAMP()
{
date +%Y%m%d-%H%M%S
}
# example output function
NOTE()
{
echo "NOTE `STAMP`: $*"
}
ERR()
{
echo "ERR `STAMP`: $*" >&2
}
catch_example()
{
# Example use
catch NOTE ERR find /proc -ls
}
查看示例的第二行(向下滚动)