Bash 无法向远程主机执行多个expect send语句
我需要使用expect在远程PC上编辑/etc/host文件。 以下是代码部分:Bash 无法向远程主机执行多个expect send语句,bash,expect,Bash,Expect,我需要使用expect在远程PC上编辑/etc/host文件。 以下是代码部分: /usr/bin/expect << EOD set timeout 10 set send_slow { 1 .01 } spawn -noecho ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -o ConnectTimeout=10 ${USRNAME}@${REMOTE_PC} expect {
/usr/bin/expect << EOD
set timeout 10
set send_slow { 1 .01 }
spawn -noecho ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -o ConnectTimeout=10 ${USRNAME}@${REMOTE_PC}
expect {
timeout { send_user "\nTimeout while oonnecting to ${REMOTE_PC}\n"; exit }
"*No route to host*" { send_user "\n${REMOTE_PC} not reachable\n"; exit }
"*assword: " { send -s "$PASSWORD\r\r" }
}
expect {
timeout { send_user "\nTimeout waiting for prompt\n"; exit }
# "$PS1" refers to the system prompt setup in .bash_profile.
"$PS1" {
send -s "(grep -xq -P '${MY_SVR_IP}\tcm' /etc/hosts) && echo __CM_FOUND || echo __CM_NOTFOUND\r"
expect {
# Order is IMPORTANT! __NOTFOUND must comes first.
__CM_NOTFOUND {
send_user "\nNot Found!\n";
send -s "sudo sed -i -r '/127.0.0.1 +Local_Host/i # Modified on ${MOD_DATE}.' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +Local_Host)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +cm)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r '/\#127.0.0.1 +cm/a ${MY_SVR_IP}\tcm' /etc/hosts \r";
send "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts\r";
send_user "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts \r";
send -s "exit\r"
}
# Do nothing, if found. NOTE: Cannot put any comments after end brace.
__CM_FOUND { send -s "exit\r" }
}
}
}
EOD
但不会执行后续行。
为什么?
感谢您提前提出建议。谢谢
#=============================================================
我将脚本修改为:
/usr/bin/expect -d << EOD
set timeout 3
set send_slow { 1 .01 }
set prompt_re {*${USERNAME}@${REMOTE_PC}:*\$ $}
spawn -noecho ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -o ConnectTimeout=3 ${USERNAME}@${REMOTE_PC}
expect {
timeout { send_user "\nTimeout while oonnecting to ${REMOTE_PC}\n"; exit }
"*No route to host*" { send_user "\n${REMOTE_PC} not reachable\n"; exit }
"*assword: " { send -s "$PASSWORD\r\r" }
}
expect {
timeout { send_user "\nTimeout waiting for prompt\n"; exit }
-re "$prompt_re" {
send_user "\nSuccessfully login to ${REMOTE_PC}.\n"
}
}
send -s "(grep -xq -P '${MY_SVR_IP}\tcm' /etc/hosts) && echo __CM_FOUND || echo __CM_NOTFOUND\r"
expect {
__CM_NOTFOUND {
send_user "\nNot Found!\n";
send -s { "sudo sed -i -r '/127.0.0.1 +Local_Host/i # Modified on ${MOD_DATE}.' /etc/hosts \r" }
send -s { "sudo sed -i -r 's/(127.0.0.1 +Local_Host)/#\1/g' /etc/hosts \r" }
send -s { "sudo sed -i -r 's/(127.0.0.1 +cm)/#\1/g' /etc/hosts \r" }
send -s { "sudo sed -i -r '/\#127.0.0.1 +cm/a ${MY_SVR_IP}\tcm' /etc/hosts \r" }
send_user "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts \r"
send -s "exit\r"
}
__CM_FOUND { send -s "exit\r" }
}
EOD
PS1
将仅存在于交互式shell中
在调试输出中是否看到以下内容
send:将“密码\r\r”发送到{exp4}
expect:“(spawn_id exp4)是否与全局模式”匹配?
这个空字符串是$PS1
不幸的是,处理提示的惯用方法是以正则表达式模式对其进行硬编码:
# This is the patten to match a prompt on the remote host, alter as needed.
# This matches a dollar sign and a space at the end of the prompt
set prompt_re {\$ $}
我发现避免深度嵌套的expect命令有助于提高可读性:
spawn -noecho ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -o ConnectTimeout=10 ${USRNAME}@${REMOTE_PC}
expect {
timeout { send_user "\nTimeout while oonnecting to ${REMOTE_PC}\n"; exit }
"*No route to host*" { send_user "\n${REMOTE_PC} not reachable\n"; exit }
"*assword: "
}
send -s "$PASSWORD\r\r"
expect {
timeout { send_user "\nTimeout waiting for prompt\n"; exit }
-re $prompt_re
}
send -s "(grep -xq -P '${MY_SVR_IP}\tcm' /etc/hosts) && echo __CM_FOUND || echo __CM_NOTFOUND\r"
expect {
__CM_NOTFOUND {
# Order is IMPORTANT! __NOTFOUND must comes first.
send_user "\nNot Found!\n";
send -s "sudo sed -i -r '/127.0.0.1 +Local_Host/i # Modified on ${MOD_DATE}.' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +Local_Host)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +cm)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r '/\#127.0.0.1 +cm/a ${MY_SVR_IP}\tcm' /etc/hosts \r";
send "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts\r";
send_user "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts \r";
send -s "exit\r"
}
__CM_FOUND {
# Do nothing, if found. NOTE: Cannot put any comments after end brace.
send -s "exit\r"
}
}
注意不要像这样将注释放在expect块中:expect将把它们视为模式操作对。Expect将看到Expect命令行:
expect {
timeout { send_user "\nTimeout waiting for prompt\n"; exit }
{#} {"$PS1"}
refers {to}
the {system}
prompt {setup}
in {.bash_profile.}
"$PS1" {
send -s "(grep -xq -P '${MY_SVR_IP}\tcm' /etc/hosts) && echo __CM_FOUND || echo __CM_NOTFOUND\r"
expect {
{#} {Order}
is {IMPORTANT!}
__NOTFOUND {must}
comes {first.}
__CM_NOTFOUND {
send_user "\nNot Found!\n";
send -s "sudo sed -i -r '/127.0.0.1 +Local_Host/i # Modified on ${MOD_DATE}.' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +Local_Host)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +cm)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r '/\#127.0.0.1 +cm/a ${MY_SVR_IP}\tcm' /etc/hosts \r";
send "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts\r";
send_user "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts \r";
send -s "exit\r"
}
{#} {Do}
nothing, {if}
found. {NOTE:}
Cannot {put}
any {comments}
after {end}
brace. {__CM_FOUND}
{ send -s "exit\r" }
}
}
}
使用
expect-d后使用expect-d(expect:does“\r\n”((spawn\u id exp4)匹配glob模式“\uuuu CM\u NOTFOUND”?no“\uu CM\u FOUND”?不欢迎使用Ubuntu 16.04.6 LTS(GNU/Linux 4.4.15-uno1483-rt23+i686)*文档:*管理:*支持:上次登录:Tue May 25 18:55:15 2021 expect:does”\r\n(\r\n欢迎访问Ubuntu 16.04.6 LTS(GNU/Linux 4.4.15-uno1483-rt23+i686)\r\n\r\n*文档:\r\n*管理:\r\n*支持:\r\n\r\n上次登录:Tue May 25 18:55:15 2021“(生成id exp4)匹配全局模式“\u CM\u未找到”?否“\u CM\u未找到”?否[support@agv0001:~]$ [support@agv0001:~]$(grep-xq-P'cm'/etc/hosts)&&echo_uuucm_FOUND | echo uu CM_NOTFOUND uu CM_NOTFOUND尝试在每次发送后添加一个expect
等待shell提示,否则您可能发送得太快。将expect想象为一个人,他只会在看到下一个shell提示后发送新命令。是否存在打字错误?是否应该是-re$prompt\re
?是的,q你说得对。
spawn -noecho ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -o ConnectTimeout=10 ${USRNAME}@${REMOTE_PC}
expect {
timeout { send_user "\nTimeout while oonnecting to ${REMOTE_PC}\n"; exit }
"*No route to host*" { send_user "\n${REMOTE_PC} not reachable\n"; exit }
"*assword: "
}
send -s "$PASSWORD\r\r"
expect {
timeout { send_user "\nTimeout waiting for prompt\n"; exit }
-re $prompt_re
}
send -s "(grep -xq -P '${MY_SVR_IP}\tcm' /etc/hosts) && echo __CM_FOUND || echo __CM_NOTFOUND\r"
expect {
__CM_NOTFOUND {
# Order is IMPORTANT! __NOTFOUND must comes first.
send_user "\nNot Found!\n";
send -s "sudo sed -i -r '/127.0.0.1 +Local_Host/i # Modified on ${MOD_DATE}.' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +Local_Host)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +cm)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r '/\#127.0.0.1 +cm/a ${MY_SVR_IP}\tcm' /etc/hosts \r";
send "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts\r";
send_user "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts \r";
send -s "exit\r"
}
__CM_FOUND {
# Do nothing, if found. NOTE: Cannot put any comments after end brace.
send -s "exit\r"
}
}
expect {
timeout { send_user "\nTimeout waiting for prompt\n"; exit }
{#} {"$PS1"}
refers {to}
the {system}
prompt {setup}
in {.bash_profile.}
"$PS1" {
send -s "(grep -xq -P '${MY_SVR_IP}\tcm' /etc/hosts) && echo __CM_FOUND || echo __CM_NOTFOUND\r"
expect {
{#} {Order}
is {IMPORTANT!}
__NOTFOUND {must}
comes {first.}
__CM_NOTFOUND {
send_user "\nNot Found!\n";
send -s "sudo sed -i -r '/127.0.0.1 +Local_Host/i # Modified on ${MOD_DATE}.' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +Local_Host)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r 's/(127.0.0.1 +cm)/#\1/g' /etc/hosts \r";
send -s "sudo sed -i -r '/\#127.0.0.1 +cm/a ${MY_SVR_IP}\tcm' /etc/hosts \r";
send "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts\r";
send_user "grep -B3 -A2 -P '${MY_SVR_IP}\tcm' /etc/hosts \r";
send -s "exit\r"
}
{#} {Do}
nothing, {if}
found. {NOTE:}
Cannot {put}
any {comments}
after {end}
brace. {__CM_FOUND}
{ send -s "exit\r" }
}
}
}