一、Python pexpect 庫的使用
在終端中許多命令都有與用戶交互的場景,例如切換用戶時需要手動輸入密碼,安裝應用有時要輸入默認配置等。這對 shell 自動化腳本十分不便。expect 命令的出現解決了上述問題。下面簡單演示 shell 中使用 expect 命令自動輸入密碼切換用戶並用切換后的用戶執行命令的流程。
原版 shell 執行 expect 命令演示
在終端按以下步驟執行(其中 123 是 root 用戶的密碼),可以登錄到 root 用戶的終端。
user@host:~$ expect
expect1.1> set tiemout 5
5
expect1.2> spawn su
spawn su
3712
expect1.3> expect "Password" "密碼"
Password: expect1.4> send "123\n"
expect1.5> interact
root@host:/home/user#
這樣就進入了 root 用戶的終端。這時或許會有人說,寫這么多,還不如直接執行 su 命令。事實上,真正的 expect 指令不會像這樣直接在終端運行,而是作為腳本來運行。下面使用 Python 的 os 庫中的 system 函數模擬在終端輸入命令。以腳本的方式運行,感受 expect 的強大。
from os import system as shell_command
# expect 腳本如下
script = """#!/usr/bin/expect
set timeout 5
spawn su
expect {
"Password" {send "123\\\\r"}
"密碼" {send "123\\\\r"}
}
send "whoami > whoami.txt\\\\r"
send "exit\\\\r"
expect eof
"""
# print(script)
# 先清理先前測試殘留的文件
shell_command("rm -f whoami.txt")
# 用 echo 的方式創建 expect 腳本
shell_command("echo '" + script + "' > /tmp/shell_expect_su_script.sh")
shell_command("chmod +x /tmp/shell_expect_su_script.sh")
shell_command("/tmp/shell_expect_su_script.sh")
print("\ncat whoami.txt = ", end="")
shell_command("cat whoami.txt")
spawn su
Password:
root@Master: /home/hadooproot@Master/home/hadoop# whoami > whoami.txt
root@Master: /home/hadooproot@Master/home/hadoop# exit
exit
cat whoami.txt = root
0
在上面的例子中,無需手動輸入 root 用戶的密碼,即可登錄進 root 用戶的終端,並將自己的名稱(root)寫入文件 whoami.txt 中。由此看來,有了 expect 命令,使全自動化腳本成為了可能。
Python 自動化腳本 pexpect 庫演示
在 Python 中,提供了 pexpect 庫,可以十分方便地使用 Python 代碼實現 expect 命令的功能。下面演示使用 pexpect 切換到 root 用戶並在 text.txt 中寫入一些數據,最后用 os 庫的 system 函數執行 cat 命令讀取 text.txt 文件內容驗證執行結果。
import pexpect, os
# 先清理先前殘留下的文件
os.system("rm -f text.txt")
os.system("ls -l | grep 'text.txt'")
process = pexpect.spawn("su")
process.timeout = 5
process.expect("Password")
process.sendline("123")
process.sendline("echo export PATH=/home/hadoop > text.txt")
process.sendline("EOF")
process.close()
os.system("ls -l text.txt")
os.system("cat text.txt")
-rw-r--r-- 1 root root 25 Mar 10 23:30 text.txt
export PATH=/home/hadoop
0
可見,使用 Python 代碼可以更加方便地實現 expect 的功能。
expect 腳本講解
現在,講解一下上述例子中 expect 腳本中的內容。
#!/usr/bin/expect # 這條語句告訴操作系統用來解釋腳本的程序的位置
set timeout 5 # 設置超時時間,單位是秒。超過這個時長,就認為執行失敗並退出。
# 例如在這里,如果密碼 ‘123’ 是錯誤的,那么等待 5 秒后無法登錄進去就會退出。
spawn su # spawn 是 expect 的內部指令,后面接要在 shell 執行的命令,
# 這樣 expect 會開啟一個新的進程來執行這個命令並監聽它。
expect { # expect 的中文是 ‘期待’ 的意思,顧名思義,expect 會期待出現指定的字符串。
"Password" {send "123\r"} # 雙引號(必須寫雙引號,不能是單引號)中是 expect 指令等待 spawn 生成的程序
# (這里是 su)出現的字符串。
#
# 這里當 su 命令執行后出現 “Password” 時,就發送 send 后面的字符串 "123\r"
# 給 su 命令。
#
# 注意:123 后面的 \r 不能少,它表示我們輸入 123 后按下的回車鍵。
"密碼" {send "123\r"} # 與上面一樣,只不過這里 expect 期待的是 “密碼” 而不是 “Password”。
}
send "whoami > whoami.txt\r" # 此時不出意外的話已經進入 root 的終端了,這里直接發送終端命令即可執行,同樣注意 \r 不能少。
send "exit\r" # 發送命令 exit 退出 root 的終端。
expect eof # 結束整個 expect 命令
參考:
shell expect的簡單用法
Linux expect 介紹和用法
python之pexpect模塊
#!/bin/bash