期望带有可选 ssh-agent 密码提示的脚本?
expect script with optional ssh-agent passphrase prompt?
我想在 expect 的帮助下自动执行数据库备份:首先,脚本使用 建立从远程数据库端口到本地计算机的转发端口ssh。然后我使用数据库实用程序转储所有数据库。
因此,我在 bash 脚本中有以下 expect 脚本:
#!/bin/sh
expect <<- DONE
set timeout -1
# port-forward remote database port 3306 to local port 3307
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnNT -L 3307:localhost:3306 someuser@example.com
expect {
# conditional prompt appears in case ssh-agent is not active
"*.ssh/id_rsa':*" {
send -- "$SSH_PASSPHRASE\r"
}
# ?!?!?!? What to expect here in case ssh-agent is active, therefore no password needed, and therefore no prompt appears?
}
# dump remote database by connecting to forwarded port
spawn mysqldump --all-databases --user=root --password --protocol=TCP --host=localhost --port=3307 --verbose --result-file=${DB_DUMP_FILE}
expect {
# prompt appears for database password
"*?asswor?:*" {
send -- "$PASSWORD_MYSQL_ROOT\r"
}
}
expect eof
DONE
此脚本可能 运行 在两种情况下:
- 要么 ssh-agent 当前未激活。在这种情况下,生成的 ssh 进程将提示
Enter passphrase for key '${HOME}/.ssh/id_rsa':
,第一个 expect 规则很匹配,并正确发送 SSH 密码.
- 或ssh-agent当前处于活动状态。在这种情况下,生成的 ssh 进程静默建立端口转发,不需要或提示输入 SSH 密码。
我正在努力让这两种情况在我的 expect 脚本中工作。特别是,我不知道如何修改脚本以使 "silent" active-ssh-agent 为 "expected",因此 expect 脚本可以继续启动数据库转储。
我尝试了期望多个事物方法(在上面?!?!?!?
评论位置)通过尝试:
- 期待换行,
- 期待我的 shell 提示,
- 期待
eof
。
但是 none 有效。我在 StackExchange 周围发现了类似的问题和建议的解决方案:
* How to use expect with optional prompts?
* https://superuser.com/q/412259/137881
* TCL / Expect Scripting - Using a conditional statement to attempt a secondary login password
但是 solutino 似乎会导致代码重复:每个条件提示都意味着复制和粘贴脚本的其余部分,这使得脚本很快变得复杂,每个 ssh 语句都有嵌套的条件提示。
我如何让 expect 在 ssh 不提示输入 passphrase/password 的情况下优雅地工作,因为SSH 代理?
是的,这很有趣。由于您使用的是 ssh -N
,您不会在远程主机上启动任何进程,ssh 会话就在那里。你只需要睡几秒钟,希望隧道已经建立起来。
set timeout 2
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnNT -L 3307:localhost:3306 someuser@example.com
expect {
# conditional prompt appears in case ssh-agent is not active
"*.ssh/id_rsa':*" { send -- "$SSH_PASSPHRASE\r" }
# wait until the timeout, then carry on with the rest of the script
timeout
}
set timeout -1
# ...
或者,删除 -N
,然后您可以在远程主机上看到提示。
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnT -L 3307:localhost:3306 someuser@example.com
# ..........................................^^^^
expect {
# conditional prompt appears in case ssh-agent is not active
"*.ssh/id_rsa':*" { send -- "$SSH_PASSPHRASE\r" }
# I assume your prompt ends with a dollar sign and a space
-re {$ $}
}
现在您可以生成 mysql 命令并与之交互。
我想在 expect 的帮助下自动执行数据库备份:首先,脚本使用 建立从远程数据库端口到本地计算机的转发端口ssh。然后我使用数据库实用程序转储所有数据库。
因此,我在 bash 脚本中有以下 expect 脚本:
#!/bin/sh
expect <<- DONE
set timeout -1
# port-forward remote database port 3306 to local port 3307
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnNT -L 3307:localhost:3306 someuser@example.com
expect {
# conditional prompt appears in case ssh-agent is not active
"*.ssh/id_rsa':*" {
send -- "$SSH_PASSPHRASE\r"
}
# ?!?!?!? What to expect here in case ssh-agent is active, therefore no password needed, and therefore no prompt appears?
}
# dump remote database by connecting to forwarded port
spawn mysqldump --all-databases --user=root --password --protocol=TCP --host=localhost --port=3307 --verbose --result-file=${DB_DUMP_FILE}
expect {
# prompt appears for database password
"*?asswor?:*" {
send -- "$PASSWORD_MYSQL_ROOT\r"
}
}
expect eof
DONE
此脚本可能 运行 在两种情况下:
- 要么 ssh-agent 当前未激活。在这种情况下,生成的 ssh 进程将提示
Enter passphrase for key '${HOME}/.ssh/id_rsa':
,第一个 expect 规则很匹配,并正确发送 SSH 密码. - 或ssh-agent当前处于活动状态。在这种情况下,生成的 ssh 进程静默建立端口转发,不需要或提示输入 SSH 密码。
我正在努力让这两种情况在我的 expect 脚本中工作。特别是,我不知道如何修改脚本以使 "silent" active-ssh-agent 为 "expected",因此 expect 脚本可以继续启动数据库转储。
我尝试了期望多个事物方法(在上面?!?!?!?
评论位置)通过尝试:
- 期待换行,
- 期待我的 shell 提示,
- 期待
eof
。
但是 none 有效。我在 StackExchange 周围发现了类似的问题和建议的解决方案: * How to use expect with optional prompts? * https://superuser.com/q/412259/137881 * TCL / Expect Scripting - Using a conditional statement to attempt a secondary login password
但是 solutino 似乎会导致代码重复:每个条件提示都意味着复制和粘贴脚本的其余部分,这使得脚本很快变得复杂,每个 ssh 语句都有嵌套的条件提示。
我如何让 expect 在 ssh 不提示输入 passphrase/password 的情况下优雅地工作,因为SSH 代理?
是的,这很有趣。由于您使用的是 ssh -N
,您不会在远程主机上启动任何进程,ssh 会话就在那里。你只需要睡几秒钟,希望隧道已经建立起来。
set timeout 2
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnNT -L 3307:localhost:3306 someuser@example.com
expect {
# conditional prompt appears in case ssh-agent is not active
"*.ssh/id_rsa':*" { send -- "$SSH_PASSPHRASE\r" }
# wait until the timeout, then carry on with the rest of the script
timeout
}
set timeout -1
# ...
或者,删除 -N
,然后您可以在远程主机上看到提示。
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnT -L 3307:localhost:3306 someuser@example.com
# ..........................................^^^^
expect {
# conditional prompt appears in case ssh-agent is not active
"*.ssh/id_rsa':*" { send -- "$SSH_PASSPHRASE\r" }
# I assume your prompt ends with a dollar sign and a space
-re {$ $}
}
现在您可以生成 mysql 命令并与之交互。