Bash 找不到名为“的频道”&引用;期望脚本

Bash 找不到名为“的频道”&引用;期望脚本,bash,ssh,expect,Bash,Ssh,Expect,我有两个结合使用的脚本。这是因为我有大量的命令需要批量发送到路由器/交换机 完全披露我没有写这些脚本,它们是由不再与我合作的人写的,我对expect的了解非常有限 第一个脚本(脚本A)允许我从一个中央框在多个设备上同时执行脚本,同时将脚本结果输出到一个文件 #!/bin/bash let j=0; let sleeptime=20; let numberInstance=20; if [ $# -lt "3" ] then echo "Missing Parameters:"

我有两个结合使用的脚本。这是因为我有大量的命令需要批量发送到路由器/交换机

完全披露我没有写这些脚本,它们是由不再与我合作的人写的,我对expect的了解非常有限

第一个脚本(脚本A)允许我从一个中央框在多个设备上同时执行脚本,同时将脚本结果输出到一个文件

#!/bin/bash

let j=0;
let sleeptime=20;
let numberInstance=20;
if [ $# -lt "3" ]
then
    echo "Missing Parameters:"
    echo "start <script-name> <output-directory> <sites-file>"
    exit 1
fi


for s in `cat ${3}`
do

        echo Processing: $s on `date`;
        ./$1 ${s}${4}  > ./$2/${s}-${4} &
        let j+=1;


if [ `expr $j % $numberInstance` -eq 0 ]
        then
echo sleeping for ${sleeptime} seconds...sites processed: $j;
                sleep $sleeptime;
fi
done
在这种情况下,我知道这些位置将失败。但是,当我一次运行数百个时,我希望提示符能够这样说:

Failed to execute script on Site1.
Failed to execute script on Site2.
Failed to execute script on Site3.
Failed to execute script on Site4.
我不知道如何让脚本A意识到脚本B的失败

预期脚本:

#!/usr/bin/expect

proc _jgetRouterIPs {} {
set file [open router-list r]
  while {![eof $file]} {
               set buff [read $file ]
              }
close $file
return $buff
}

proc ssh2rtr { rtr usr pwd } {
 spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
if { $ppret == 0 } {
return $spawn_id;
else { return -1;}
}}


proc processPrompts { rtr usr pwd sess_id status } {
      set timeout 666;
      set spawn_id $sess_id;
      set fw_prompt  {\nuser@[0-9]{4}\-[A-Z]{2}-S2[>|#]{1}};
      set fwprompt1  {user@[0-9]{4}-[A-Z]{2}-S2\%\s};

if { $status < 2 } {
      expect {
      -re $fw_prompt { return 0;}
      -re $fwprompt1 {send "cli\r"; return 0;}

      "no)?" {  send "yes\r";
       processPrompts $rtr $usr $pwd $sess_id 0;
        }


      "assword:" {
                send "${pwd}\r";
       if { $status} { return 1;}
       processPrompts $rtr $usr $pwd $sess_id 1;

        }

     timeout     { send_user "\nTimeout on SSH!!!\n"; return 8; } ;#no response from telnet/ssh
     default     { send_user "\nSSH Unknown Error!!!\n"; return 9;  } ;#unknown error has occurred.
} ;#end expect 
} ;#end if
}



set site [lindex $argv 0];
set sw1 "${site}s1";
set sw2 "${site}s2";
set fw "${site}fw1";
set fw_prompt  {\nuser@[0-9]{4}\-[A-Z]{2}-S2[>#]{1}};
set fw_prompt1  {user@[0-9]{4}-[A-Z]{2}-S2%\s};

set sshret  [ ssh2rtr $sw2 user NotMyPassword ]
if { $sshret != -1 } {
                set spawn_id $sshret;
} else {
                send_user "Error Connecting...!!!";
}
        set timeout 666;


send "edit\r";
expect -re $fw_prompt;
send "rollback\r";
expect -re $fw_prompt;
*more commands will go here*
#/usr/bin/expect
过程{
设置文件[打开路由器列表r]
而{![eof$file]}{
设置buff[读取$file]
}
关闭$file
返回$buff
}
proc ssh2rtr{rtr usr pwd}{
生成ssh-l$usr$rtr;
设置sess_id$spawn_id;
设置ppret[processPrompts$rtr$usr$pwd$sess_id 0];
如果{$ppret==0}{
返回$spawn_id;
else{return-1;}
}}
proc PROCESSPROMPS{rtr usr pwd sess_id status}{
设置超时666;
设置spawn_id$sess_id;
设置fw_提示符{\n用户@[0-9]{4}-[A-Z]{2}-S2[>|#]{1};
设置fwprompt1{user@[0-9]{4}-[A-Z]{2}-S2\%\s};
如果{$status<2}{
期待{
-re$fw_提示符{返回0;}
-re$fwprompt1{send“cli\r;返回0;}
“否”?“{发送“是”\r”;
processPrompts$rtr$usr$pwd$sess_id 0;
}
“assword:”{
发送“${pwd}\r”;
如果{$status}{return 1;}
processPrompts$rtr$usr$pwd$sess_id 1;
}
超时{send_user“\nTimeout on SSH!!!\n”return 8;};#telnet/SSH没有响应
默认{send_user“\nSSH未知错误!!!\n”返回9;};#发生未知错误。
}##结束期待
}##如有必要,结束
}
设置站点[lindex$argv 0];
设置sw1“${site}s1”;
设置sw2“${site}s2”;
设置fw“${site}fw1”;
设置fw#u提示符{\n用户@[0-9]{4}-[A-Z]{2}-S2[>#]{1};
设置fw_prompt1{user@[0-9]{4}-[A-Z]{2}-S2%\s};
设置sshret[ssh2rtr$sw2用户NotMyPassword]
如果{$sshret!=-1}{
设置spawn_id$sshret;
}否则{
发送用户“连接错误…!!!”;
}
设置超时666;
发送“编辑\r”;
expect-re$fw_提示;
发送“回滚\r”;
expect-re$fw_提示;
*这里会有更多的命令*

当您在进程中使用
spawn
时,这是带有expect的常见WTF。请注意expect手册页中的一个警告:

Expect对范围界定持相当开放的观点。特别是,Expect程序特定命令读取的变量将首先从本地范围中查找,如果找不到,则在全局范围中查找。例如,这样就无需在使用expect编写的每个过程中放置“全局超时”。另一方面,写入的变量总是在本地范围内(除非发出了“全局”命令)。这导致的最常见问题是在过程中执行spawn时。在过程之外,spawn_id不再存在,因此由于作用域的原因,生成的进程不再可访问将“
全局繁殖id
”添加到该过程。


从长远来看,通过开发良好的编码卫生,您将真正帮助您自己:正确的缩进对于可读代码至关重要。我还建议您将bash代码粘贴到中,其中有许多改进需要改进。请看一看您可以使用哪种方法仅使用shell代码编写Expect脚本。感谢您的输入。我用拼写检查器清理了狂欢节。然而,我的问题不是代码不起作用,它起作用了,只是很好。我只是想找到一种吸引人的方式,向终端显示终端设备无法访问。这是它唯一一次失败,而且出于显而易见的原因,它应该失败。
#!/usr/bin/expect

proc _jgetRouterIPs {} {
set file [open router-list r]
  while {![eof $file]} {
               set buff [read $file ]
              }
close $file
return $buff
}

proc ssh2rtr { rtr usr pwd } {
 spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
if { $ppret == 0 } {
return $spawn_id;
else { return -1;}
}}


proc processPrompts { rtr usr pwd sess_id status } {
      set timeout 666;
      set spawn_id $sess_id;
      set fw_prompt  {\nuser@[0-9]{4}\-[A-Z]{2}-S2[>|#]{1}};
      set fwprompt1  {user@[0-9]{4}-[A-Z]{2}-S2\%\s};

if { $status < 2 } {
      expect {
      -re $fw_prompt { return 0;}
      -re $fwprompt1 {send "cli\r"; return 0;}

      "no)?" {  send "yes\r";
       processPrompts $rtr $usr $pwd $sess_id 0;
        }


      "assword:" {
                send "${pwd}\r";
       if { $status} { return 1;}
       processPrompts $rtr $usr $pwd $sess_id 1;

        }

     timeout     { send_user "\nTimeout on SSH!!!\n"; return 8; } ;#no response from telnet/ssh
     default     { send_user "\nSSH Unknown Error!!!\n"; return 9;  } ;#unknown error has occurred.
} ;#end expect 
} ;#end if
}



set site [lindex $argv 0];
set sw1 "${site}s1";
set sw2 "${site}s2";
set fw "${site}fw1";
set fw_prompt  {\nuser@[0-9]{4}\-[A-Z]{2}-S2[>#]{1}};
set fw_prompt1  {user@[0-9]{4}-[A-Z]{2}-S2%\s};

set sshret  [ ssh2rtr $sw2 user NotMyPassword ]
if { $sshret != -1 } {
                set spawn_id $sshret;
} else {
                send_user "Error Connecting...!!!";
}
        set timeout 666;


send "edit\r";
expect -re $fw_prompt;
send "rollback\r";
expect -re $fw_prompt;
*more commands will go here*