Here Document,简称Heredoc,是Shell脚本中一种特殊的输入重定向方式,允许你插入多行文本到命令中,作为输入数据源。它由一个起始标记界定开始,以相同标记结束(通常该标记位于一行的开始),并且在结束标记前可以包含任意文本,甚至是变量和命令的输出。
Heredoc设计用于简化向脚本或命令提供多行数据的过程,避免了手动输入或交互式对话的需求,特别适用于自动化脚本的编写。
虽然read
命令直接与Here Document无关,但提到免交互,可以对比说明。常规使用read
时需要用户逐行输入,而使用Heredoc,可以预先定义好要输入的多行文本,实现自动化:
- # 使用Here Document代替read的交互过程
- cat <<EOF
- This is the first line.
- This is the second line.
- EOF
Here Document在非交互式地设置用户密码时非常有用,避免了手动输入密码的步骤:
- sudo passwd username <<EOF
- newPassword123
- newPassword123 # 确认密码
- EOF
注意:出于安全考虑,某些系统或版本的passwd
命令可能不接受来自stdin的密码输入。
在Heredoc中,可以方便地插入和使用变量,实现动态内容生成:
- greeting="Hello"
- name="Alice"
- cat <<EOF
- ${greeting}, ${name}!
- EOF
Heredoc支持所有文本格式化控制,包括转义序列(如\n
换行、\t
制表符)和多行文本,适用于生成格式化输出,如配置文件、HTML等:
- #bash
- cat <<EOF
- <html>
- <head>
- <title>Welcome</title>
- </head>
- <body>
- <h1>Hello, World!</h1>
- </body>
- </html>
- EOF
尽管不推荐作为主要的注释方式,但Here Document可以用作多行注释的一种非传统方法:
- : <<'COMMENT'
- 这是一个
- 多行注释
- 不会展开变量
- COMMENT
注意:使用单引号包围结束标记以阻止变量展开,保持注释内容原样输出。然而,标准的井号#
仍然是推荐的单行或多行注释方式。
Expect 是一个强大的自动化和测试工具,它使用Tcl语言编写,专为处理交互式程序设计,如那些需要用户输入密码或对提示做出响应的程序。通过期望(expect)特定的输出并发送(send)相应的回复,expect脚本能模拟人类与命令行应用程序的交互,从而实现自动化操作,无需人工介入。
在Linux系统中,expect通常作为一个独立的软件包存在,可以通过包管理器安装:
sudo apt-get install expect
sudo yum install expect
或 sudo dnf install expect
brew install expect
每个expect脚本通常以#!/usr/bin/expect
作为第一行,指定了脚本的解释器。
\r
来模拟回车键。expect可以使用-exact
, -glob
, -regexp
等选项来指定匹配模式的类型。
用于设置变量,如set variable value
。
在满足expect条件后,使用exp_continue
可以继续执行下一次expect,而不是退出当前循环。
类似于print或echo,但只输出到控制台,不发送给进程,用于调试或状态反馈。
脚本可以通过1,2等变量获取命令行参数,如set arg1 [lindex $argv 0]
。
基本结构包括spawn启动进程,一系列expect和send交互,以及最后的流程控制。
脚本可以直接执行,或在shell脚本中调用expect命令执行。
- #!/usr/bin/expect
- set username "newuser"
- set password "secretpassword"
- spawn useradd $username
- expect "Enter new UNIX password:"
- send "$password\r"
- expect "Retype new UNIX password:"
- send "$password\r"
- interact
- #!/usr/bin/expect
- set user "remote_username"
- set host "remote_host"
- set password "remote_password"
- spawn ssh $user@$host
- expect {
- "(yes/no)?" { send "yes\r"; exp_continue }
- "password:" { send "$password\r" }
- }
- interact
- #!/usr/bin/expect
- set ftp_server "ftp.example.com"
- set ftp_user "ftp_username"
- set ftp_password "ftp_password"
- spawn ftp $ftp_server
- expect "Name .*:"
- send "$ftp_user\r"
- expect "Password:"
- send "$ftp_password\r"
- expect "ftp>"
- send "ls\r"
- expect "ftp>"
- send "quit\r"
这些案例展示了expect在自动化管理任务,如用户管理、远程登录和文件传输等方面的强大功能,通过模拟用户交互,实现无须人工干预的脚本执行。