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 の組み合わせ、クローン、起動スクリプトなどを使用して) パスワード要求で停止します。

アクティブな 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
}

主なポイント:

  • シェルを生成してそれにコマンドを送信する代わりに、いくつかのコマンドを生成していました
  • アクションブロックの外にコメントを入れます(詳細は以下をご覧ください)
  • interact コマンドはユーザーに制御を戻しますが、これは cron スクリプトでは望ましくありません。

マルチパターンの expect ブロックのコメントが悪い理由:

Tcl は、他の言語のようにコマンドを処理しません。コメント文字は、コマンドが実行できる場所に表示された場合にのみ、コメントのように機能します。これが、expect/tcl コードで次のような行末コメントが表示される理由です。

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

そのセミコロンが欠落している場合#、コマンドの別の引数として処理されます。

マルチパターンのexpectコマンドは次のようになります

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 に答える