0

我有以下期望脚本将本地文件夹与远程文件夹同步:

    #!/usr/bin/expect -f
    # Expect script to interact with password based commands. It synchronize a local 
    # folder with an remote in both directions.
    # This script needs 5 argument to work:
    # password = Password of remote UNIX server, for root user.
    # user_ip = user@server format
    # dir1=directory in remote server with / final
    # dir2=local directory with / final
    # target=target directory
    # set Variables
    set password [lrange $argv 0 0] 
    set user_ip [lrange $argv 1 1]   
    set dir1 [lrange $argv 2 2]   
    set dir2 [lrange $argv 3 3]   
    set target [lrange $argv 4 4]   
    set timeout 10   
    # now connect to remote UNIX box (ipaddr) with given script to execute
    spawn rsync -ruvzt -e ssh $user_ip:$dir1$target $dir2
    match_max 100000
    expect {
    -re ".*Are.*.*yes.*no.*" {
    send "yes\n"
    exp_continue
    }
    # Look for password prompt
    "*?assword*" {
    # Send password aka $password 
    send -- "$password\r"
    # send blank line (\r) to make sure we get back to gui
    send -- "\r"
    interact
    }
    }
    spawn rsync -ruvzt -e ssh $dir2$target $user_ip:$dir1
    match_max 100000
    expect {
    -re ".*Are.*.*yes.*no.*" {
    send "yes\n"
    exp_continue
    }
    # Look for password prompt
    "*?assword*" {
    # Send password aka $password 
    send -- "$password\r"
    # send blank line (\r) to make sure we get back to gui
    send -- "\r"
    interact
    }
    }
    spawn ssh $user_ip /home/pi/bash/cerca_del.sh $dir1$target
    match_max 100000
    expect {
    -re ".*Are.*.*yes.*no.*" {
    send "yes\n"
    exp_continue
    }
    # Look for passwod prompt
    "*?assword*" {
    # Send password aka $password 
    send -- "$password\r"
    # send blank line (\r) to make sure we get back to gui
    send -- "\r"
    interact
    }
    }

如果我在 gnome_terminal 窗口中执行它,它可以正常工作,但如果我在前台执行(比如我们使用 ALT+F2 组合,或者使用 crone,或者使用启动脚本),它会停止输入密码请求。

如果期望活动的 Windows 终端需要正确交互,我没有找到信息。

其他人试验这种奇怪的行为?这是一个功能还是一个错误?有什么解决办法吗?

谢谢你。

4

2 回答 2

0

您的脚本有几个错误。快速重写:

#!/usr/bin/expect -f
# Expect script to interact with password based commands. It synchronize a local 
# folder with an remote in both directions.
# This script needs 5 argument to work:
# password = Password of remote UNIX server, for root user.
# user_ip = user@server format
# dir1=directory in remote server with / final
# dir2=local directory with / final
# target=target directory
# set Variables

lassign $argv password user_ip dir1 dir2 target
set timeout 10   

spawn /bin/sh
set sh_prompt {\$ $}
expect -re $sh_prompt
match_max 100000

# now connect to remote UNIX box (ipaddr) with given script to execute
send rsync -ruvzt -e ssh $user_ip:$dir1$target $dir2
expect {
    -re ".*Are.*.*yes.*no.*" {
        send "yes\r"
        exp_continue
    }
    "*?assword*" {
        # Look for password prompt
        # Send password aka $password 
        send -- "$password\r"
        # send blank line (\r) to make sure we get back to gui
        send -- "\r"
    }
    -re $sh_prompt
}

send rsync -ruvzt -e ssh $dir2$target $user_ip:$dir1
expect {
    -re ".*Are.*.*yes.*no.*" {
        send "yes\r"
        exp_continue
    }
    "*?assword*" {
        send -- "$password\r"
        send -- "\r"
    }
    -re $sh_prompt
}

send ssh $user_ip /home/pi/bash/cerca_del.sh $dir1$target
expect {
    -re ".*Are.*.*yes.*no.*" {
        send "yes\r"
        exp_continue
    }
    "*?assword*" {
        send -- "$password\r"
        send -- "\r"
    }
    -re $sh_prompt
}

要点:

  • 你生成了几个命令,而不是生成一个 shell 并将命令发送给它
  • 您在操作块之外发表了评论(下面有更多详细信息)
  • 交互命令将控制权交还给用户,这是您在 cron 脚本中不想要的

为什么多模式期望块中的注释不好:

Tcl 不像其他语言那样对待命令:注释字符仅在它出现在命令可以去的地方时才起到注释的作用。这就是为什么你会在这样的 expect/tcl 代码中看到行尾注释

command arg arg ...     ;# this is the comment

如果缺少该分号,#则将是句柄作为命令的另一个参数。

多模式期望命令看起来像

expect pattern1 {body1} pattern2 {body2} ...

或带有续行

expect \
    pattern1 {body1} \
    pattern2 {body2} \
    ...

或者在大括号中(最好的风格,正如你所写的)

expect {
    pattern1 {body1} 
    pattern2 {body2} 
    ...
}

模式前面可以有选择地使用 -exact、-regexp、-glob 和 --

当您在其中发表评论时,如下所示:

expect {
    pattern1 {body1} 
    # this is a comment
    pattern2 {body2} 
    ...
}

Expect 不会在那里寻找新命令:它将像这样解释块

expect {
    pattern1 {body1} 
    #        this
    is       a
    comment  pattern2
    {body2}  ...
}

当您将注释放入动作主体中时,就像我在上面所做的那样,那么您是安全的,因为主体是根据 Tcl 的规则进行评估的(这里有 12 个完整的规则)。

呸。希望有帮助。我强烈建议您查看本书以了解所有详细信息。

于 2013-06-15T02:22:36.927 回答
0

当我对格伦的回答发表评论时,我发现问题不在于终端窗口,而在于调用脚本的方式。我的期望脚本被另一个 BASH 脚本调用了几次,粗鲁的行是:“/path/expect-script-name.exp [parameters]”。打开终端窗口(在任何桌面环境中),我可以通过以下方式执行调用者脚本:“/path/bash-script-name.sh”。这样,一切都运行良好,因为 shebang 用于调用正确的 shell(在本例中为 EXPECT)。我在启动系统列表中添加了在非聚焦终端窗口实例中工作的 BASH 脚本(即 EXPECT 脚本的调用者脚本)。最后一种方法会出错。

解决方案是在 BASH 脚本中显式调用 EXPECT 脚本,方式为:“expect /path/expect-script-name.exp”。

我发现如果没有这个显式调用,shell DASH 会管理所有脚本(包括 EXPECT 脚本)。

于 2015-08-19T13:32:36.820 回答