1. 简介

Linux Shell 的自动交互在很多场景下会使用到,比如我们需要批量运行一些需要输入参数进行交互的命令时,此时 Shell 的自动交互就能将我们从重复无聊的手动交互中解放出来。

2. 方法

以下我们通过 ssh-keygen 命令生成密钥来举例说明各个方法的使用。

2.1 内联输入重定向符

内联输入重定向符是一种输入重定向符,该输入重定向符用于从命令行中指定用于输入重定向的数据,因此可以用它来实现 Shell 的自动交互。

  • 需要注意的是,在以下方式中,两个「标记符」EOF (也可以设为其他的字符串)之间的每一行为直接对应每一条交互输入。因此,给出的参数前后不能有多余的空格和 Tab,否则也会被当作输入参数的一部分。
1
2
3
4
5
6
7
#!/bin/bash

ssh-keygen -t rsa -C "example@163.com" << EOF
$HOME/Tmp/example


EOF
  • 若需要消除给出的参数前面多余的 Tab,特别是当 ssh-keygen 处于多层缩进区域时,如果顶行写会导致脚本不美观。此时我们可以使用 <<- 来忽略每行参数前面的前导 Tab(注意只能消除 Tab,不能消除空格)。
1
2
3
4
5
6
7
#!/bin/bash

ssh-keygen -t rsa -C "example@163.com" <<-EOF
$HOME/Tmp/example


EOF

【注】关于「内联输入重定向符」更多详细介绍参见LinuxShell重定向和管道

2.2 管道符

除了使用内联输入重定向符,也可以使用管道符来实现 Shell 自动交互。

1
2
3
#!/bin/bash

echo -e "$HOME/Tmp/example\n\n\n" | ssh-keygen -t rsa -C "example@163.com"

2.3 expect 命令

expect 是一个专门用来实现 Shell 自动化交互的工具,有些 Linux 发行版可能没有预装,需要自行安装。

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/expect

spawn ssh-keygen -t rsa -C "example@163.com"
expect "Enter file in which to save the key"
send "$env(HOME)/Tmp/example\n"
expect "Enter passphrase"
send "\n"
expect "Enter same passphrase again"
send "\n"
expect off
  • expect 类似于 bash 作为一个解释器,因此使用 expect 时需要在脚本开头指定 #!/usr/bin/expect 而不是 #!/bin/bash
  • expect 下定义的变量称为 TCL 变量,它和 Shell 下的变量是不互通的。因此 expect 不能直接使用 Shell 下的环境变量,若要使用 Shell 下 ENV 环境变量则需使用 $env(ENV) 语法。

expect 脚本中:

  • spawn 后面指定要实现自动交互的命令。
  • expect 用来等待要识别的消息。
  • send 用来发送输入参数。
  • expect off 用来指明自动交互结束。

【注】更多关于 expect 工具的详解参见官方手册 man expect

附录

更多详细介绍参考以下资料: