shell腳本使用expect遠程登錄kill進程中遇到的問題 Shell中expect


 

需求:shell 腳本遠程登錄多台主機並kill 進程

腳本

#!/usr/bin/expect -f


password=6666
path=/app/work/aam/
topath=/app/yytester


while read -r ipline
do
expect <<EOF
spawn ssh app@${ipline}
set timeout 3
expect {
"*yes/no" {send "yes\n"; exp_continue}
"*password" {send "${password}\r"}
}
expect -re ".*\[\$#\]"
#send "whoami\r"
#send "ps -ef|grep java|grep 8406|awk '{print \$2}'|xargs kill -9\r"      
#send "ps -ef|grep java|grep -v grep|grep 8406|awk '{print \$2}'|awk '{print \$2}'\r"
send "ps -ef|grep app|grep -v grep|grep 8406|awk '{print \\\$2}'|xargs kill -9\r"
expect -re ".*\[\$#\]"
send "ps -ef|grep app|grep -v grep|grep java\r"
expect -re ".*\[\$#\]"
send "exit\r"
expect eof
EOF
done < passFile

其中會遇到兩個錯誤

問題1: can't read “2”: no such variable 

#send "ps -ef|grep java|grep 8406|awk '{print \$2}'|xargs kill -9\r"      這樣寫會 Error : can't read “2”: no such variable 

不知道原因 baidu bing 找到了一篇文章給我提示:

https://blog.csdn.net/weixin_33913332/article/details/92936868  我以轉發

原因:

expect 腳本遠程 kill 進程,需要對特殊字符進行轉義,$2 需要 \ 轉義,否則會把 2 是當作一個變量。

解決方法:

send "kill -9 `ps -ef|grep java|grep -v grep|awk '{print \$2}'`\r" 這種也是不對的 我試過還是報錯 於是找來到了expect需要轉義的符號列表
應該寫成{print \\\$2} 這個問題解決了

expect需要轉義的符號列表
\ 需轉義為 \\\
} 需轉義為 \}
[ 需轉義為 \[
$ 需轉義為 \\\$
` 需轉義為 \`
" 需轉義為 \\\"

引用連接:https://blog.csdn.net/secondjanuary/article/details/21775953

問題2:找不到進程

yytest>ps -ef|grep java|grep 8406|awk '{print }'|xargs kill -9
kill: can't find process "app"
kill 1: Operation not permitted
kill: can't find process "13:06"
kill: can't find process "?"

不知道原因 baidu bing 找到了一篇文章給我提示:

https://blog.csdn.net/tengdazhang770960436/java/article/details/53906263

我將兩篇原文放到下邊做個記錄

Shell+expect 完成遠程切換用戶啟動服務

expect 腳本:文件名:expect_ssh

#!/usr/bin/expect set host [lindex $argv 0] set username [lindex $argv 1] set password [lindex $argv 2] spawn ssh $username@$host expect { "(yes/no)?" { send "yes\n" expect "*assword:" { send "$password\n"} } "*assword:" { send "$password\r" } } set pwd 1234567 expect "$" send "su -\r" expect "Password:" send "$pwd\r" expect "*]#" send "kill -9 `ps -ef|grep java|grep -v grep|awk '{print \$2}'`&& su - tomcat -c /usr/local/tomcat6/bin/startup.sh &&su - tomcat7 -c /usr/local/tomcat7/bin/startup.sh\r" #但是這種寫法得到的進程號是本地的進程號 send "\r" send "exit\r" send "exit\r" expect eof
 

bash 腳本:調用 expect 腳本,bash 文件名:bash_ssh.sh

#!/bin/sh rpm -q expect &>/dev/null if [ $? -ne 0 ]; then echo "install expect......" yum install -y expect > /dev/null fi list_file=$1 cat $list_file | while read line do host_name=`echo $line | awk '{print $1}'` username=`echo $line | awk '{print $2}'` password=`echo $line | awk '{print $3}'` ./expect_ssh $host_name $username $password done
 

建立 host.list 文件

# touch host.list 192.168.66.130 tom 123456 192.168.66.131 tom 123456
 

使用方法:

sh bash_ssh.sh host.list
 

 調試中的錯誤:

read "2": no such variable
 

原因:

expect 腳本遠程 kill 進程,需要對特殊字符進行轉義,$2 需要 \ 轉義,否則會把 2 是當作一個變量。

解決方法:

send "kill -9 `ps -ef|grep java|grep -v grep|awk '{print \$2}'`\r"

轉載於:https://blog.51cto.com/stuart/2089771

linux 遠程殺掉進程

傾-盡 2016-12-28 10:29:38 7113 收藏
展開
第一步:獲取進程號
pid=$(ssh root@$remote_host "ps -ef | grep ${tomcat_name} | grep -v grep | awk '{print $2}'"| awk '{print $2}')
1
第二步:殺掉進程
ssh root@$remote_host "kill -9 ${pid}"
1
注意:
殺掉遠程進程跟殺掉本地進程不一樣,殺掉本地進程只需要一句話就可以搞定了:

ps -ef | grep ${tomcat_name} | grep -v grep | awk '{print $2}'|xargs kill -9
1
但是殺掉遠程的進程不一樣,因為過濾的結果會被整體返回,如果在遠程執行這個殺掉進程的命令:

ssh root@$remote_host "ps -ef | grep ${tomcat_name} | grep -v grep | awk '{print $2}' | xargs kill -9"
1
你會得到錯誤的提示:

kill process java -jar tomcat-8081
kill: can't find process "root"
kill: can't find process "09:42"
kill: can't find process "?"
kill: can't find process "00:00:44"
kill: can't find process "/opt/tools/jdk1.7.0_67/bin/java"
kill: can't find process "-Djava.util.logging.config.file=/opt/tools/tomcat-8081/conf/logging.properties"
kill: can't find process "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
kill: can't find process "-Ddisconf.env=rd"
kill: can't find process "-Ddisconf.conf_server_host=192.168.100.15:8015"
kill: can't find process "-Ddisconf.app=ync365"
kill: can't find process "-Ddisconf.version=1.0.0"
kill: can't find process "-Ddisconf.user_define_download_dir=./classes"
kill: can't find process "-Ddisconf.enable.remote.conf=true"
kill: can't find process "-Djdk.tls.ephemeralDHKeySize=2048"
kill: can't find process "-Djava.endorsed.dirs=/opt/tools/tomcat-8081/endorsed"
kill: can't find process "-classpath"
kill: can't find process "/opt/tools/tomcat-8081/bin/bootstrap.jar:/opt/tools/tomcat-8081/bin/tomcat-juli.jar"
kill: can't find process "-Dcatalina.base=/opt/tools/tomcat-8081"
kill: can't find process "-Dcatalina.home=/opt/tools/tomcat-8081"
kill: can't find process "-Djava.io.tmpdir=/opt/tools/tomcat-8081/temp"
kill: can't find process "org.apache.catalina.startup.Bootstrap"
kill: can't find process "start"

這是因為你執行的遠程命令會返回如下結果:

root 7314 1 7 09:51 pts/0 00:00:17 /opt/tools/jdk1.7.0_67/bin/java -Djava.util.logging.config.file=/opt/tools/apache-tomcat-7.0.70/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/opt/tools/apache-tomcat-7.0.70/endorsed -classpath /opt/tools/apache-tomcat-7.0.70/bin/bootstrap.jar:/opt/tools/apache-tomcat-7.0.70/bin/tomcat-juli.jar -Dcatalina.base=/opt/tools/apache-tomcat-7.0.70 -Dcatalina.home=/opt/tools/apache-tomcat-7.0.70 -Djava.io.tmpdir=/opt/tools/apache-tomcat-7.0.70/temp org.apache.catalina.startup.Bootstrap start
1
然后 xargs kill -9 會把上面的所有的空格隔開的進程給刪除一遍,實際上他們根本不是進程,只是一個進程下面返回的描述而已,我們真正需要的進程號是第二個 7314 這個進程,因此我們需要把返回的字符串再次過濾一遍,這樣就能夠得到真正的進程號了。
原文鏈接:https://blog.csdn.net/tengdazhang770960436/java/article/details/53906263

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM