2013-03-13 248 views
10

在shell腳本的循環中,我連接到各種服務器並運行一些命令。例如shell腳本ssh命令退出狀態

#!/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 

在這裏,我跑「回聲$ HOST」和「PWD」命令和我得到通過退出狀態「回聲$?」。

我的問題是,我想能夠存儲我在某些變量中遠程運行的命令的退出狀態,然後(根據命令是否成功)將日誌寫入本地文件。

任何幫助和代碼表示讚賞。

回答

19

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 
+0

你是說我需要單獨ssh運行每個命令,以便我可以提取他們的退出狀態?我試圖在我的真實代碼中在相同的ssh會話中運行至少5個命令。 – 2013-03-13 17:01:03

+0

嗨,@larsks。你能解釋一下'ssh localhost exit 10'的含義嗎?這意味着用一個明確的10作爲狀態碼來執行ssh localhost?在這裏,exit是ssh或linux命令'exit'的選項? – 2017-01-19 15:26:19

+0

請記住,ssh命令的基本語法是'ssh '。所以在上面的答案中,'exit 10'是傳遞給遠程shell的命令。 – larsks 2017-01-19 19:50:04

0

一個有趣的方法是使用反引號檢索局部變量中每個ssh命令集的整個輸出,或者甚至用特殊字符(爲了簡單起見說「:」)som ething這樣的:在這之後

export MYVAR=`ssh $HOST 'echo -n ${HOSTNAME}\:;pwd'` 

可以使用awk分裂MYVAR到您的結果,並繼續bash的測試。

0

也許準備日誌文件的另一邊,管它到stdout,就像這樣:

ssh -n [email protected] 'x() { local ret; "[email protected]" >&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 

當然,你可以做的更好解析的或使其適應你的whishes日誌文件應如何樣子。請注意,遠程程序的未捕獲正常stdout被寫入stderr(請參閱x()中的重定向)。

如果你需要一個配方來捕獲和準備日誌文件命令的輸出,下面是https://gist.github.com/hilbix/c53d525f113df77e323d這樣一個捕獲器的副本 - 但是,這是一個更大的樣板文件來「在shell的當前上下文中運行某些東西,後處理標準輸出+標準錯誤,而不會干擾返回代碼「:

# 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 "[email protected]" "$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 
} 

看到倒數第二行中的示例(向下滾動)

2

可以作爲簡單的退出狀態分配給一個變量做:

var_name= $? 

正好在您嘗試檢查的命令之後。之前不要echo $?$?的新值將是echo(通常爲0)的退出代碼。