相互作用のないXshellプログラミング(EOFおよび相互作用のないことを期待)
記事のディレクトリ
1つ、ヒアドキュメントは相互作用がありません
1.関連する概念
-
I / Oリダイレクトを使用して、ftp、cat、readコマンドなどの対話型プログラムにコマンドのリストを提供します
-
標準入力の代わりになることで、スクリプト開発者は一時ファイルを使用して入力情報を作成するのではなく、「ファイル」を直接生成して「コマンド」の標準入力として使用できます。ヒアドキュメントは、非対話型のプログラムやコマンドでも使用できます。
2.文法形式
命令 <<标记
...
#标记之间是传入内容
...
标记
3.注意が必要な事項
- マークには任意の正当な文字(通常はEOF)を使用できます
- 終了マークは、前に文字を付けずに上部グリッドに書き込む必要があります
- 終了タグの後に文字(スペースを含む)を含めることはできません
- 開始タグの前後のスペースは省略されます
4.相互作用のない例
1)行数の統計を実現するインタラクションフリーモード
[root@localhost ~]#wc -l <<EOF
> 123
> 456
> qwe
> asd
> EOF
4
2)入力を受け取り、読み取りコマンドを介して印刷します
注:割り当てることができるコンテンツは1行のみです
[root@localhost ~]#read i <<EOF
> hello
> nihao
> EOF
[root@localhost ~]#echo $i
hello
[root@localhost ~]#read i <<EOF
> hahaha nihao
> EOF
[root@localhost ~]#echo $i
hahaha nihao
3)passwdを介してユーザーのパスワードを設定します
注:パスワードは2回入力する必要があります
[root@localhost ~]#passwd ww &> /dev/null <<EOF
> 123123 #这两行是输入的密码和确认的密码
> 123123
> EOF
[root@localhost ~]#su ww1 #由于root用户切换到普通用户不需要密码,所以想要验证密码是否更新就需要先切换到一个普通用户,然后再切换到更改密码的普通用户
[ww1@localhost root]$ su ww #输入更改后的密码,登录成功
密码:
[ww@localhost root]$
4)変数置換をサポートする
ファイルを書き込むとき、最初に変数を実際の値に置き換え、次にcatコマンドで書き込みを完了します。
[root@localhost /免交互] # vim th.sh
[root@localhost /免交互] # ls
th.sh
[root@localhost /免交互] # cat th.sh #查看脚本内容
#!/bin/bash
file="th.txt"
i="home"
cat > $file <<EOF
I am going $i
EOF
[root@localhost /免交互] # chmod +x th.sh
[root@localhost /免交互] # ./th.sh #执行脚本
[root@localhost /免交互] # ls #执行脚本以后会发现自动建了个文件
th.sh th.txt
[root@localhost /免交互] # cat th.txt #查看文件,变量已被替换
I am going home
5)変数全体に値を割り当てます
変数全体に値を割り当ててから、echoコマンドを使用して変数の値を出力します。
[root@localhost /免交互] # vim ztfz.sh
[root@localhost /免交互] # chmod +x ztfz.sh
[root@localhost /免交互] # ./ztfz.sh
今天周一了。 好唉!今天要上班了!
[root@localhost /免交互] # cat ztfz.sh
#!/bin/bash
var="好唉!今天要上班了!"
myvar=$(cat <<EOF
今天周一了。
$var
EOF
)
echo $myvar
注:上記のスクリプトの最後で、echo -e "myvar"を使用して改行を実行します
6)変数置換の機能をオフにします
変更や置換なしで、文字の元の外観に従って出力します
[root@localhost /免交互] # vim ztfz.sh
[root@localhost /免交互] # ./ztfz.sh
今天周一了。
$var
[root@localhost /免交互] # cat ztfz.sh
#!/bin/bash
var="好唉!今天要上班了!"
myvar=$(cat <<'EOF'
今天周一了。
$var
EOF
)
echo -e "$myvar"
7)各行の前の[Tab]文字を削除します
マークの前に「-」を追加して、各行の先頭の[Tab]文字を抑制します
[root@localhost /免交互] # cat ztfz.sh
#!/bin/bash
var="上面的Tab它没了!"
myvar=$(cat <<-EOF
前面有个空格,你信不信?
前面有个假的Tab字符!
$var
EOF
)
echo -e "$myvar"
[root@localhost /免交互] # ./ztfz.sh
前面有个空格,你信不信?
前面有个假的Tab字符!
上面的Tab它没了!
事実上、中国語のスクリプトはcat -Aを使用して多くの文字を表示します。英語でスクリプトを作成します。cat-Aを使用して、含まれている文字を表示します。次に、スクリプトを実行した後、今日は月曜日であることがわかりました。上部のグリッドが欠落しており、Tab文字がなくなったことを示しています。
[root@localhost /免交互] # vim school.sh
[root@localhost /免交互] # cat -A school.sh
#!/bin/bash$
var="Great! I am going to school!"$
myvar=$(cat <<-EOF$
^IToday is Monday.$
$var$
EOF$
)$
echo -e "$myvar"$
[root@localhost /免交互] # ./school.sh
Today is Monday.
Great! I am going to school!
8)複数行コメント
- Bashのデフォルトのコメントは「#」です。このコメントメソッドは単一行コメントのみをサポートします
- ヒアドキュメントの導入により、複数行コメントの問題が解決されます。「:」は、何もしない空のコマンドを表します。ミドルマーク領域の内容は実行されず、bashによって無視されるため、バッチコメントの効果を実現できます。
[root@localhost /免交互] # cat school.sh
#!/bin/bash
var="Great! I am going to school!"
: myvar=$(cat <<-EOF
Today is Monday.
$var
EOF
)
echo -e "$myvar"
[root@localhost /免交互] # ./school.sh
[root@localhost /免交互] #
注:コマンドから区切るには、コロン「:」の後にスペースが必要です。
2、相互作用を期待しない
- シェルスクリプトのインタラクティブな問題を解決するために、自動制御とテストによく使用されるtcl言語に基づくツール
ツールがインストールされているかどうかを照会し、インストールされていない場合はインストールします
rpm -q expect
rpm -q tcl
yum install -y expect
1.基本的なコマンド
1)スクリプトインタプリタ
このファイルは、どのシェルが使用されているかを示すために、expectスクリプトで最初に導入されます。
#!/usr/bin/expect
2)スポーン
スポーンの後には通常、セッションを開き、プロセスを開始し、後続の対話情報を追跡するコマンドが続きます。
例:spawn passwd root
3)期待する
-
最後の出力結果に指定された文字列が含まれているかどうかを判断します。含まれている
場合はすぐに
戻ります。含まれていない場合は、タイムアウト期間を待ってから戻ります。 -
spawnによって開始されたプロセスの出力のみをキャプチャできます。
-
コマンドの実行後に出力を受け取り、期待される文字列と一致させるために使用されます
4)送信
ユーザーの入力をシミュレートするために文字列をプロセスに送信します。このコマンドは自動的に入力して改行することはできません。通常は\ r(キャリッジリターン)または\ nを追加します。
例如:发送密码
方式一:
expect "密码" {send "123456\r"} #同一行send部分要有{}
方式二:
expect "密码"
send "123456\r" #换行send部分不需要有{}
方式三:
expect #只要匹配了其中一个情况,执行相应的send语句后退出该expect语句
{
"密码1" {send "123456\r"}
"密码2" {send "123123\r"}
"密码3" {send "abc123\r"}
}
5)ターミネーター
-
eofを期待する
インタラクションの終了を示し、実行の終了を待機し、スポーンに対応して元のユーザーに戻ります。
たとえば、rootユーザーに切り替える場合、expectスクリプトはデフォルトで10秒間待機します。コマンドが実行されると、デフォルトは10秒間そのままになり、自動的に元のユーザーに戻ります。
-
相互作用する
実行が完了すると、対話状態が維持され、制御がコンソールに移されます。元の端末に戻るのではなく、ターゲット端末に留まります。この時点で、手動で操作できます。対話後のコマンド対話後に終了を追加するなど、機能しません。rootユーザーを終了しません。対話がない場合は、リモート端末にとどまるのではなく、ログイン後にログアウトします。
インタラクションを使用すると、元のターミナルに戻るのではなく、ターミナルに留まります。たとえば、rootユーザーに切り替えると、常にrootユーザーの状態になります。たとえば、別のサーバーにSSHで接続すると、元のターミナルサーバーに切り替えるのではなく、常にターゲットサーバーターミナルにいることになります。
注:eofを期待して対話するには、2つのうちの1つしか選択できません。
6)セット
期待のデフォルトのタイムアウト期間は10秒です。セッションタイムアウト期間はsetコマンドで設定できます。タイムアウト期間が制限されていない場合は、-1に設定する必要があります。
例:set timeout 30
7)exp_continue
- exp_continueは、特定の期待判断項目に追加されるため、項目が一致した後も、期待判断文の他の項目と一致し続けることができます。exp_continueは、制御ステートメントのcontinueステートメントに似ています。期待値が命令の実行を継続できることを示します。
次に例を示します。次の例では、対話型出力にyes / noまたは* passwordがあるかどうかを判別します。yes / noに一致する場合は、yesを出力し、判断を再実行します。* passwordに一致する場合は、abc123を出力し、expectステートメントを終了します。
注:exp_continueを使用する場合、パスワードの入力後にプロセスを終了するpasswdなどのコマンドに従う場合は、expect {}の外にexpecteofを追加しないでください。これは、spawnプロセスが終了した後、デフォルトでeofをexpectに送信するためです。これは後でexpecteofにつながります。実行エラー。
expect {
"(yes/no)" {send "yes\r"; exp_continue;}
"*password" {set timeout 300; send "abc123\r";}
}
注:exp_continueを使用する場合、パスワードの入力後にプロセスを終了するpasswdなどのコマンドに従う場合は、expect {}の外にexpecteofを追加しないでください。これは、spawnプロセスが終了した後、デフォルトでeofをexpectに送信するためです。これは後でexpecteofにつながります。実行エラー。
8)send_user
- send_userは、echoと同等のechoコマンドを意味します
9)受信パラメータ
- expectスクリプトは、bashコマンドラインから渡されたパラメーターを受け入れ、[lindex $ argvn]を使用してそれを取得できます。その中で、nは0から始まり、それぞれ1番目、2番目、3番目のパラメーターを表します。
例:
set hostname [lindex $argv 0] #相当于hostname=$1
set password [lindex $argv 1] # 相当于password=$2
3つ目は、相互作用の例がないことを期待する
1)直接実行することを期待する
例:suスイッチユーザー
#!/usr/bin/expect
set timeout 5 #超时时间
set username [lindex $argv 0]
set password [lindex $argv 1]
spawn su $username #开始追踪命令
expect "密码" {send "$password\r"} #免交互执行,捕捉信息并匹配
interact #把控制权交给控制台
#或者expect eof
注:rootユーザーが作成したスクリプトで最初に他のユーザーに実行許可を与える必要がある場合は、コマンドchmod a + xqhyh.shを使用してすべてのユーザーに実行許可を与えることができます。次に、通常のユーザーに切り替えます。rootは通常のユーザーに切り替えるためにパスワードを必要としないため、通常のユーザーに切り替えてからスクリプトを実行する必要があります。
2)埋め込み実行
- 実行と処理を容易にするために、expectプロセスをシェルに統合します
例:ユーザーを作成してパスワードを設定する
#!/bin/bash
#设定变量
user=$1
password=$2
useradd $user
#上方非交互命令放在except外面
/usr/bin/expect <<EOF
#开启一个进程追踪passwd命令。expect只能捕捉该进程信息
spawn passwd $user
#满足匹配信息就向进程发送信息
expect "新的*" {send "${password}\r"}
expect "重新*" {send "${password}\r"}
#结束符
expect eof
EOF
の結果
3)ssh自動ログインを実現する
①期待して直接実行する
#!/usr/bin/expect
set timeout 5
set hostname [lindex $argv 0]
set password [lindex $argv 1]
spawn ssh $hostname
expect {
#假如连接失败,直接退出
"Connection refused" exit
#未知主机名或服务时,直接退出
"Name or service not known" exit
#如果匹配到to continue,则发送后面字符串
"to continue" {send "yes\r";exp_continue}
#如果匹配到password,发送后面字符串
"password:" {send "$password\r"}
}
#interact后面的命令不起作用
interact
exit
ホスト192.168.2.4にリモートでログインしました。
②埋め込み
#!/bin/bash
hostname=$1
password=$2
/usr/bin/expect <<EOF
spawn ssh $hostname
expect {
"(yes/no)" {send "yes\r";exp_continue}
"*password" {send "$password\r"}
}
expect "*]#" {send "ifconfig\r"}
expect eof
EOF