Shell Scripting Tricks - Here Document Free Interaction and Expect Automation Interaction

Posted by PHPHorizons on Wed, 15 Sep 2021 18:38:33 +0200


In a real production environment, writing shell scripts will inevitably encounter some interactive interfaces, such as raid s and extensions, which require interaction, so we need to use the following non-interactive operations to achieve true shell script automation.

1. Here Document exempt from interaction

1. Overview

  • Provide a list of commands to an interactive program or command, such as a ftp, cat, or read command, using I/O redirection

  • Is an alternative to standard input, which helps script developers build input information without using temporary files, but instead generate a "file" in place and use it as standard input for a "command"

  • Here Document can also be used with non-interactive programs and commands

2. Grammar Format

command <<sign
content    #Tags are passed in directly

3. Notes

  • Markers can use any legal character (usually EOF)

  • The end marker must be top-notched, with no characters (including spaces) before or after it.

  • Spaces before and after the start tag are omitted

4. Examples

1. Implement row count statistics in an interactive way

[root@localhost ~]# wc -l <<EOF
> xjj1
> xjj2

(2) Receive input and print through read command

  • Replace variables with actual values when writing to a file
  • Then write with the cat command
[root@localhost ~]# vim


cat > $file <<EOF
I'd like some $i
[root@localhost ~]# .          #Execute script first
[root@localhost ~]# ls    xjj3.txt   
[root@localhost ~]# cat xjj3.txt
I'd like some money

(3) assign values to variables as a whole, and then print out the values of variables by echo command

[root@localhost ~]# vim


name="OMG! xjj come!"
myname=$(cat <<EOF
It's a beautiful day
today is sunday
school starts again tomorrow
echo $myname
[root@localhost ~]# . 
It's a beautiful day today is sunday school starts again tomorrow OMG! xjj come!

(4) Turn off variable substitution function

  • This will output as the original character, without any modifications or substitutions

[root@localhost ~]# . 
It's a beautiful day today is sunday school starts again tomorrow $name

Create a yum source

[root@localhost ~]# cat > test.repo <<EOF
> [test]
> name=test
> baseurl=file:///mnt
> enabled=1
> gpgcheck=0
Writing 2: cat <<EOF > local.repo
 Writing 3: tee test1.txt <<EOF

Multi-line notes

  • Bash's default comment is'#', which only supports single-line comments
  • The introduction of Here Document solves the problem of multiline comments
  • ":" Represents an empty command to do nothing
  • The contents of the intermediate markup area will not be executed and will be ignored by bash, thus achieving the effect of bulk commenting

[root@localhost ~]# . 
OMG! xjj come! 

2. Expect Automation Interaction

1. Overview

  • expect is a free programming tool language that is often used to communicate between automated and interactive tasks without human intervention
  • Expct requires support for the Tcl programming language. To run expect on your system, you must first install Tcl
rpm -q expect
rpm -q tcl
yum -y install expect 			#Either yum or CD-ROM installation

2. Basic Commands

(1) Script Interpreter

  • The expect script first introduces a file indicating which shell is being used


  • spawn is usually followed by a Linux command that opens a session, starts a process, and tracks subsequent interactions
example: spawn passwd root          ##Track the process of starting a password change


  • Determines if the last input contains the specified string and returns immediately if it does, otherwise it waits for a time-out to return
  • Only output from processes started by spawn can be captured
  • Used to receive output after command execution and then match the expected string


  • Send a string to the process to simulate user input
  • This command does not automatically reroute carriages, typically with \r (Enter) or \n
  • Mode 1
expect "Password" {send "abc123\r"}			#send section on the same line must have {}
  • Mode 2
expect "Password"
send "$abc123\r"						#The newline send section does not require {}
  • Mode 3
expect "Support multiple branches

expect  {        	#Whenever one of these situations is matched, the expect statement is exited after executing the corresponding send statement
"Password 1 {send "abc123\r"}"
"Password 2 {send "123123\r"}"
"Password 3 {send "123123\r"}"


expect eof
  • Indicates the end of interaction, waits for the end of execution, falls back to the original user, corresponding to spawn
  • For example, switching to the root user, the expect script defaults to waiting for 10s, and when the command is executed, it defaults to staying for 10s, which automatically cutes back to the original user
  • When the execution is completed, the interactive state is maintained, control is given to the console, and control is left at the target terminal, at which point manual operation is possible. Commands after the interact do not work, such as the interact stays at the terminal without returning to the original terminal, such as switching to the root user, and it stays at the root user state all the time.
  • For example, ssh to another server will always be in the target server terminal, not the original server back
  • Note: expect eof and interact can only choose one from the other


  • The default timeout for expect is 10 seconds. Session timeout can be set with the set command or -1 if timeout is not limited
set timeout 30


  • After an exp_continue is attached to an expect judgement, it can be matched to other items in the expect judgement
  • exp_continue is similar to a continue statement in a control statement in that it allows expect to continue executing instructions down
  • The following example will determine whether yes/no or *password exists in the interactive output, and output yes if yes/no is matched and execute the judgment again.If *assword matches, output 123123 and end the expect statement
"(yes/no)" {send "yes\r"; exp_ continue; }
"*password" {set timeout 300; send "123123\r";}


  • Send_user stands for echo command, equivalent to echo

Receive parameters

  • Expct scripts can accept parameters passed from the bash command line, obtained using [lindex $argv n], where n starts at 0 and represents the first, second, and third, respectively...
  • Example:
set hostname [lindex $argv 0]
##Equivalent to hostname=$1

set password [lindex $argv 1]
##Equivalent to password=$2

3.expect direct execution

  • ssh5 Interactive Logon to Remote Server
[root@localhost shell]# vim 

[root@localhost /home]#vim
#!/usr/bin/expect                     	 #Require expect's own interpreter, do not write as bash otherwise unrecognized
spawn ssh root@       	 #Open a program that is ssh Remote Login
expect {                             	 #Capture content and send password to program when password appears
        { send "123456\r"; }
interact                           				 #Interactive, otherwise exit the remote server directly

[root@localhost /home]#chmod +x              #Additional Execution Rights Required
[root@localhost /home]#./  
spawn ssh root@
root@'s password: 
Last login: Wed Sep 15 22:39:40 2021 from
  • Exit after performing an operation on the other server to execute the following script
[root@localhost /home]#vim

spawn ssh root@
expect {
        { send "123456\r"; }
expect "#"                      #When captured#When
send "ls\r"                     #Execute ls command
send "ifconfig ens33\r"         #Execute ifconfig ens33 command
send "exit\r"                   #Execute exit to log out
expect eof                      #No interaction means ending the expect program
[root@localhost /home]#chmod +x 
[root@localhost /home]#./ 
spawn ssh root@
root@'s password: 
Last login: Wed Sep 15 22:55:06 2021 from
[root@localhost ~]#ls
[root@localhost ~]#ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet  netmask  broadcast
        inet6 fe80::2161:befa:6ffd:c44b  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:01:e6:0a  txqueuelen 1000  (Ethernet)
[root@localhost ~]#exit
Connection to closed.
  • Reference location variable
[root@localhost /home]#vim 
set user root
set ip [lindex $argv 0]                #Set the first location variable to ip
set pass [lindex $argv 1]              #Set the second location variable to the login password
spawn ssh $user@$ip
expect {
        { send "$pass\r"; }
expect "#"
send "ls\r"
send "exit\r"
expect eof

[root@localhost /home]#chmod +x 
[root@localhost /home]#./ 123456
spawn ssh root@
root@'s password: 
Last login: Wed Sep 15 22:58:16 2021 from
[root@localhost ~]#ls
[root@localhost ~]#exit
Connection to closed.
  • Create user and set user password
[root@localhost /home]#vim

useradd $username
/usr/bin/expect <<-EOF
spawn passwd $username
expect {                                  #Get content and send content cannot be on the same line or execute unsuccessfully
        "New password"
        { send "123456\r";exp_continue }
        "Re-enter the new password"
        { send "123456\r"; }

[root@localhost /home]#chmod +x 
[root@localhost /home]#./ xjj
spawn passwd xjj
 Change User xjj Password.
New password:
Invalid password: password less than 8 characters
 Re-enter the new password:
passwd: All authentication tokens have been successfully updated.


With expect's command for handling interactions, interactive processes such as ssh login, FTPLogin, etc. is written on a script to automate. It can be used in environments where multiple servers need to perform the same operation. It can greatly improve the efficiency of system administrators. With it, you can even execute a script to complete the building and maintenance of distributed application systems.

Topics: Linux Operation & Maintenance shell ssh