Here Document Free interaction
Use I/O redirection to provide a command list to an interactive program or command, such as the ftp, cat, or read commands.
is an alternative to standard inputIt can help script developers not to use temporary files to build input information, but to directly produce a “file” on the spot and use it as the standard input of “command”.
Here Document can also be used with non-interactive programs and commands.
Grammar format
command <<tag ... Content # between the tags is the incoming content ... tagNotes
Mark can use any legal character (usually EOF)
The end mark must be written in the top case, and there cannot be any characters in front of it
There must also not be any characters (including spaces) after the closing tag
Spaces before and after the opening tag are omitted
Realize the statistics of the number of lines without interaction, place the content to be counted between the markers “EOF”, and directly pass the content to wc -l for statistics
[root@xue xue] wc -l <<EOF > A > B > C > D > E > EOF 5
Receive and print the input through the read command, the input value is the part between the two EOF markers, as the value of the variable i
Note The read command can only get the content of the first line and assign it to a variable.
[root@xue xue] read i << EOF > hello world > EOF [root@xue xue] echo $i hello world
Set a password for the user through passwd
passwd zhangsan << EOF >abc123 #Enter password >abc123 #confirm password >EOF
EOF cat writes a file once, replacing vim interaction
cat originally output the content of EOF to the screen, now it is redirected to the test.sh file to complete the file writing
[root@xue xue] cat << EOF >test.sh #cat > test.sh <<EOF Both ways are fine > #!/bin/bash > #test shell script > cd /boot/ > ls -l vm* > EOF
EOF | tee directly output the content of the file after inputting the file without interaction for easy inspection
tee implements both standard output and redirected output
[root@xue xue] cat <<EOF | tee abc.txt > 123 > abc > 456 > def > 789 > EOF 123 abc 456 def 789
Support variable substitution
EOF can also be used in scripts and supports substitution variables
#!/bin/bash file="EOF1.txt" i="school" cat > $file <<EOF I am going to $i EOF cat EOF1.txt
Assign the value to the variable as a whole, and then print the variable value through the echo command
#!/bin/bash var="Great! I am going to school!" myvar=$(cat <<EOF This is Line 1. Today is Monday. $var EOF ) echo "$myvar" #echo $myvar Without double quotes will cause the newline character to become a space and output on the same line. Add double quotes to keep the output formatted correctly [root@xue xue] sh eo.sh This is Line 1. Today is Monday. Great! I am going to school!
Turn off the function of variable substitution, output according to the original character, without any modification or replacement
Useful when using one script to write another script EOF
#!/bin/bash var="Great! I am going to school!" myvar=$(cat <<'EOF' #? Add single quotes to the EOF mark to turn off variable substitution This is Line 1. Today is Monday. $var EOF ) echo $myvar [root@xue xue] sh eo.sh This is Line 1. Today is Monday. $var
Remove the TAB characters before each line
-EOF can suppress the first TAB of each line but cannot work on spaces
#!/bin/bash var="Great! I am going to school!" myvar=$(cat <<-'EOF' #? Add "-" before the mark to suppress the first TAB of each line This is Line 1. Today is Monday. $var EOF ) echo $myvar
Multi-line comments
Bash’s default comment is “#”, which only supports single-line comments; the introduction of Here Document solves the problem of multi-line comments.
“:” represents an empty command that does nothing. The content in the middle marked area will not be executed and will be ignored by bash, so the effect of batch comments can be achieved.: <<EOF ... Commands between ... # are commented ... EOF#!/bin/bash var="Great! I am going to school!" : <<-EOF #Multi-line comment, the Here Document tag content at the beginning of ":" will not be executed This is Line 1. Today is Monday. $var EOF echo "abc" [root@xue xue] sh eo.sh abc
Expect
A tool based on the tcl language, which is often used for automated control and testing, and solves interaction-related problems in shell scripts.
Need to install package expect
rpm -q expect rpm -q tcl yum install -y expect
Basic commands
1. Script interpreter
The file is first introduced in the expect script, indicating which shell is used.
#!/usr/bin/expect2. spawn
spawn is usually followed by a Linux execution command, which means opening a session, starting a process, and tracking subsequent interaction information.spawn passwd root3. expect
Determine whether the specified string is included in the last output result, and if so, return immediately, otherwise wait for the timeout and return;
Can only capture the output of processes started by spawn;
Used to receive the output after the command is executed, and then match the expected string4. send
Send a character string to the process to simulate user input; this command cannot automatically return and line feed, generally add \r (carriage return) or \Method 1
expect "password" {send "abc123\r"} #The send part of the same line must have {}Method 2
expect "password" send "abc123\r" #Newline send part does not need to have {}Method 3
expect supports multiple branchesexpect { "Password 1" {send "abc123\r"} "Password 2" {send "123456\r"} "Password 3" {send "123123\r"} } #As long as one of the conditions is matched, execute the corresponding send statement and exit the expect statement5. Terminator
expect eofIndicates that the interaction is over, wait for the execution to end, and return to the original user, corresponding to spawn.
For example, if you switch to the root user, the expect script waits for 10s by default. After the command is executed, it stays for 10s by default and then automatically switches back to the original user.interactKeep the interactive state after the execution is completed, and give the control to the console, it will stay in the target terminal and will not return to the original terminal. At this time, it can be operated manually. The command after the interact does not work, such as adding exit after the interact, does not exit the root user. And if there is no interact, it will exit after the login is completed instead of staying on the remote terminal.
Using interact will stay in the terminal and will not return to the original terminal. For example, if you switch to the root user, you will always be in the root user state; for example, if you ssh to another server, you will always be in the terminal of the target server without switching back to the original server. .Note: expect eof and interact can only choose one or the other.
6.set
The default timeout time of expect is 10 seconds. The session timeout time can be set through the set command. If the timeout time is not limited, it should be set to -1.set timeout 307.exp_continue
exp_continue is appended to an expect judgment item, so that after the item is matched, it can continue to match other items in the expect judgment statement. exp_continue is similar to the continue statement in control statements. Indicates that expect is allowed to continue executing instructions downward.The following example will check whether yes/no or *password exists in the interactive output. If it matches yes/no, it will output yes and execute the judgment again; if it matches *password, it will output abc123 and end the expect statement.
To simulate SSH login for the first time, you need to enter yes to obtain the secret key and enter the password, and only need to enter the password later.
expect { "(yes/no)" {send "yes\r"; exp_continue;} #exp_continue Output yes after the condition matching is met, and continue to judge the following conditions without exiting "*password" {set timeout 300; send "abc123\r";} }Attention
When using exp_continue, if you track a command like passwd that ends the process after entering a password, do not add expect eof in addition to expect{}
Because after the spawn process ends, eof will be sent to expect by default, which will cause the subsequent expect eof to report an error8. send_user
send_user means echo command, which is equivalent to echo9. Receive parameters
The expect script can accept arguments passed from the bash command line, obtained using [lindex $argv n]. Among them, n starts from 0, respectively representing the first, second, third…. parameters.set hostname [lindex $argv 0] #equivalent to hostname=$1 set password [lindex $argv 1] #equivalent to password=$2
expect is executed directly, you need to use the expect command to execute the script
Or chmod + x, execute with ./sh
su switch user
#!/usr/bin/expect #Set timeout set timeout 5 #parameters passed in set username [lindex $argv 0] set password [lindex $argv 1] # start tracking command spawn su $username # Interaction-free execution, capturing information and matching expect "password" send "$password\r" expect "*]" #Display after entering the correct password [root@xue xue]# match *] send_user "ok" interact #Give control to the console #expect eof #Exit to the original user xue after a timeout of 5 secondsadduser wolong #create user echo abc123 | passwd --stdin wolong chmod +x exp.sh ./exp.sh wolong abc123 #sh exp.sh execution will report an error #!/usr/bin/expect
Embedded execution mode, run expect in bash. Create a user and set a password
It is generally not recommended to use the embedded execution mode for interactive commands that switch environments, such as ssh and su.
#!/bin/bash user=$1 password=$2 #Non-interactive commands are placed outside expect useradd $user #Start swap-free execution /usr/bin/expect <<-EOF #expect start flag Pass the following EOF interaction-free to /usr/bin/expect for execution spawn passwd $user #Open a process tracking passwd command, expect can only capture the process information expect "new*" send "${password}\r" expect "re*" send "${password}\r" expect eof EOF
Implement ssh automatic login
#!/usr/bin/expect set timeout 5 set hostname [lindex $argv 0] set password [lindex $argv 1] spawn ssh $hostname expect { "Connection refused" {send_user "ssh access denied\ "} #Connection failure, such as the other party's ssh service is closed "No route to host" {send_user "The host name/IP is incorrect\ "} #The server cannot be found, such as the input IP address is incorrect "(yes/no)" {send "yes\r";exp_continue} #You need to enter yes to download the key for the first connection. In order to continue to enter the password in the next step, you need to write exp_continue. It is better to exit directly after satisfying this one and no longer judge. "password:" {send "$password\r"} } interact Commands after exit #interact do not work
Create disk partition and format
1. The traditional way of writing echo to pass parameters to fdisk without interactive execution
#!/bin/bash NEWDEV=`ls /dev/sd*|grep -o 'sd[b-z]'|uniq` for VAR in $NEWDEV do echo -e "n\ p\ \ \ \ w\ " | fdisk /dev/$VAR &> /dev/null done mkfs.xfs /dev/${VAR}"1" &> /dev/nullTwo other ways of writing the echo part
echo -e "n\ p\ \ \ \ w\ " > fd.txt fdisk /dev/$VAR < fd.txtecho "n p w" | fdisk /dev/$VAR2. Expect writing method Output the corresponding characters according to the obtained text through expect and send
Use expect to implement fdisk /dev/sdb to create partitions without interaction
Requires a one-time creation
A 10G /dev/sdb1 common partition
A 2G /dev/sdb2 swap partition
A 6G /dev/sdb5 logical partition
#!/usr/bin/expect set timeout 5 spawn fdisk /dev/sdb expect "command" {send "n\r"} expect "Partition type" {send "p\r"} expect "partition number" {send "\r"} expect "start sector" {send "\r"} expect "Last sector" {send " + 10G\r"} expect "already set to Linux type" {send_user "primary partition 10G set complete"} expect "command" {send "n\r"} expect "Partition type" {send "p\r"} expect "partition number" {send "\r"} expect "start sector" {send "\r"} expect "Last sector" {send " + 2G\r"} expect "set to Linux type" {send "t\r"} expect "partition number" {send "2\r"} expect "Hex" {send "82\r"} expect "The type of partition "Linux" has been changed to "Linux swap" {send_user "swap partition 2G setup is complete"} expect "command" {send "n\r"} expect "Partition type" {send "e\r"} expect "partition number" {send "\r"} expect "start sector" {send "\r"} expect "Last sector" {send " + 6G\r"} expect "is set to Extended type" {send "n\r"} expect "Partition type" {send "l\r"} expect "start sector" {send "\r"} expect "Last sector" {send "\r"} expect "already set to Linux type" {send "w\r";send_user "extended partition 6G set complete"} #expect eof interact