Introduction To Ad-Hoc Commands

在下面的例子中,我們將演示如何使用 /usr/bin/ansible 執行 ad hoc 任務.

所謂 ad-hoc 命令是什麼呢?

(這其實是一個概念性的名字,是相對於寫 Ansible playbook 來說的.類似於在命令列敲入shell命令和 寫shell scripts兩者之間的關係)...

如果我們敲入一些命令去比較快的完成一些事情,而不需要將這些執行的命令特別儲存下來, 這樣的命令就叫做 ad-hoc 命令.

Ansible提供兩種方式去完成任務,一是 ad-hoc 命令,一是寫 Ansible playbook.前者可以解決一些簡單的任務, 後者解決較複雜的任務.

一般而言,在學習了 playbooks 之後,你才能體會到 Ansible 真正的強大之處在哪裡.

那我們會在什麼情境下去使用ad-hoc 命令呢?

比如說因為聖誕節要來了,想要把所有實驗室的電源關閉,我們只需要執行一行命令 就可以達成這個任務,而不需要寫 playbook 來做這個任務.

至於說做配置管理或部署這種事,還是要藉助 playbook 來完成,即使用 ‘/usr/bin/ansible-playbook’ 這個命令.

(關於 playbook 的使用,請參考 Playbooks )

如果你還沒有閱讀 Inventory檔案 ,最好先看一看,然後我們繼續往下.

Parallelism and Shell Commands

舉一個例子

這裡我們要使用 Ansible 的命令列工具來重啟 Atlanta 組中所有的 web 伺服器,每次重啟10個.

我們先設定 SSH-agent,將私鑰納入其管理:

$ ssh-agent bash
$ ssh-add ~/.ssh/id_rsa

如果不想使用 ssh-agent, 想通過密碼驗證的方式使用 SSH,可以在執行ansible命令時使用 --ask-pass (-k)選項, 但這裡建議使用 ssh-agent.

現在執行如下命令,這個命令中,atlanta是一個組,這個組裡面有很多伺服器,”/sbin/reboot”命令會在atlanta組下 的所有機器上執行.這裡ssh-agent會fork出10個子程序(bash),以並行的方式執行reboot命令.如前所說“每次重啟10個” 即是以這種方式實現:

$ ansible atlanta -a "/sbin/reboot" -f 10

在執行 /usr/bin/ansible 時,預設是以當前使用者的身份去執行這個命令.如果想以指定的使用者執行 /usr/bin/ansible, 請新增 “-u username”選項,如下:

$ ansible atlanta -a "/usr/bin/foo" -u username

如果想通過 sudo 去執行命令,如下:

$ ansible atlanta -a "/usr/bin/foo" -u username --sudo [--ask-sudo-pass]

如果你不是以 passwordless 的模式執行 sudo,應加上 --ask-sudo-pass (-K)選項,加上之後會提示你輸入 密碼.使用 passwordless 模式的 sudo, 更容易實現自動化,但不要求一定要使用 passwordless sudo.

也可以通過``–sudo-user`` (-U)選項,使用 sudo 切換到其它使用者身份,而不是 root(譯者注:下面命令中好像寫掉了–sudo):

$ ansible atlanta -a "/usr/bin/foo" -u username -U otheruser [--ask-sudo-pass]

Note

在有些比較罕見的情況下,一些使用者會受到安全規則的限制,使用 sudo 切換時只能執行指定的命令.這與 ansible的 no-bootstrapping 思想相悖,而且 ansible 有幾百個模組,在這種限制下無法進行正常的工作. 所以執行 ansible 命令時,應使用一個沒有受到這種限制的賬號來執行.One way of doing this without sharing access to unauthorized users would be gating Ansible with Ansible Tower, which can hold on to an SSH credential and let members of certain organizations use it on their behalf without having direct access.

以上是關於 ansible 的基礎.如果你還沒閱讀過 patterns 和 groups,應先閱讀 Patterns .

在前面寫出的命令中, -f 10 選項表示使用10個並行的程序.這個選項也可以在 Ansible的配置檔案 中設定, 在配置檔案中指定的話,就不用在命令列中寫出了.這個選項的預設值是 5,是比較小的.如果同時操作的主機數比較多的話, 可以調整到一個更大的值,只要不超出你係統的承受範圍就沒問題.如果主機數大於設定的併發程序數,Ansible會自行協調, 花得時間會更長一點.

ansible有許多模組,預設是 ‘command’,也就是命令模組,我們可以通過 -m 選項來指定不同的模組.在前面所示的例子中, 因為我們是要在 Atlanta 組下的伺服器中執行 reboot 命令,所以就不需要顯示的用這個選項指定 ‘command’ 模組,使用 預設設定就OK了.一會在其他例子中,我們會使用 -m 執行其他的模組,詳情參見 模組相關 .

Note

command 模組不支援 shell 變數,也不支援管道等 shell 相關的東西.如果你想使用 shell相關的這些東西, 請使用’shell’ 模組.兩個模組之前的差別請參考 模組相關 .

使用 shell 模組的示例如下:

$ ansible raleigh -m shell -a 'echo $TERM'

使用 Ansible ad hoc 命令列介面時(與使用 Playbooks 的情況相反),尤其注意 shell 引號的規則. 比如在上面的例子中,如果使用雙引號”echo $TERM”,會求出TERM變數在當前系統的值,而我們實際希望的是把這個命令傳遞 到其它機器執行.

在此我們已經演示了一些簡單命令如何去執行,但通常來講大多數 Ansible 模組的工作方式與簡單的指令碼不同.They make the remote system look like you state, and run the commands necessary to get it there.這一般被稱為 ‘idempotence’, 是 Ansible 設計的核心目標.但我們也認識到,能執行任意命令也是重要的,所以 Ansible 對這兩者都做支援.

File Transfer

這是 /usr/bin/ansible 的另一種用法.Ansible 能夠以並行的方式同時 SCP 大量的檔案到多臺機器. 命令如下:

$ ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts"

若你使用 playbooks, 則可以利用 template 模組來做到更進一步的事情.(請參見 module 和 playbook 的文件)

使用 file 模組可以做到修改檔案的屬主和許可權,(在這裡可替換為 copy 模組,是等效的):

$ ansible webservers -m file -a "dest=/srv/foo/a.txt mode=600"
$ ansible webservers -m file -a "dest=/srv/foo/b.txt mode=600 owner=mdehaan group=mdehaan"

使用 file 模組也可以建立目錄,與執行 mkdir -p 效果類似:

$ ansible webservers -m file -a "dest=/path/to/c mode=755 owner=mdehaan group=mdehaan state=directory"

刪除目錄(遞迴的刪除)和刪除檔案:

$ ansible webservers -m file -a "dest=/path/to/c state=absent"

Managing Packages

Ansible 提供對 yum 和 apt 的支援.這裡是關於 yum 的示例.

確認一個軟體包已經安裝,但不去升級它:

$ ansible webservers -m yum -a "name=acme state=present"

確認一個軟體包的安裝版本:

$ ansible webservers -m yum -a "name=acme-1.5 state=present"

確認一個軟體包還沒有安裝:

$ ansible webservers -m yum -a "name=acme state=absent"

對於不同平臺的軟體包管理工具,Ansible都有對應的模組.如果沒有,你也可以使用 command 模組去安裝軟體. 或者最好是來為那個軟體包管理工具貢獻一個相應的模組.請在 mailing list 中檢視相關的資訊和詳情.

Users and Groups

使用 ‘user’ 模組可以方便的建立賬戶,刪除賬戶,或是管理現有的賬戶:

$ ansible all -m user -a "name=foo password=<crypted password here>"

$ ansible all -m user -a "name=foo state=absent"

更多可用的選項請參考 模組相關 ,包括對組和組成員關係的操作.

Deploying From Source Control

直接使用 git 部署 webapp:

$ ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"

因為Ansible 模組可通知到 change handlers ,所以當源碼被更新時,我們可以告知 Ansible 這個資訊,並執行指定的任務, 比如直接通過 git 部署 Perl/Python/PHP/Ruby, 部署完成後重啟 apache.

Managing Services

確認某個服務在所有的webservers上都已經啟動:

$ ansible webservers -m service -a "name=httpd state=started"

或是在所有的webservers上重啟某個服務(譯者注:可能是確認已重啟的狀態?):

$ ansible webservers -m service -a "name=httpd state=restarted"

確認某個服務已經停止:

$ ansible webservers -m service -a "name=httpd state=stopped"

Time Limited Background Operations

需要長時間執行的命令可以放到後臺去,在命令開始執行後我們也可以檢查執行的狀態.如果執行命令後,不想獲取返回的資訊, 可執行如下命令:

$ ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"

如果你確定要在命令執行後檢查執行的狀態,可以使用 async_status 模組.前面執行後臺命令後會返回一個 job id, 將這個 id 傳給 async_status 模組:

$ ansible web1.example.com -m async_status -a "jid=488359678239.2844"

獲取狀態的命令如下:

$ ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"

其中 -B 1800 表示最多執行30分鐘, -P 60 表示每隔60秒獲取一次狀態資訊.

Polling 獲取狀態資訊的操作會在後臺工作任務啟動之後開始.若你希望所有的工作任務快速啟動, --forks 這個選項的值 要設定得足夠大,這是前面講過的併發程序的個數.在執行指定的時間(由``-B``選項所指定)後,遠端節點上的任務程序便會被終止.

一般你只能在把需要長時間執行的命令或是軟體升級這樣的任務放到後臺去執行.對於 copy 模組來說,即使按照前面的示例想放到 後臺執行檔案傳輸,實際上並不會如你所願.

Gathering Facts

在 playbooks 中有對於 Facts 做描述,它代表的是一個系統中已發現的變數.These can be used to implement conditional execution of tasks but also just to get ad-hoc information about your system. 可通過如下方式檢視所有的 facts:

$ ansible all -m setup

我們也可以對這個命令的輸出做過濾,只輸出特定的一些 facts,詳情請參考 “setup” 模組的文件.

如果你已準備好仔細研究 Playbooks ,可以繼續讀讀 Variables ,會對 facts有更多瞭解.

See also

Ansible的配置檔案
All about the Ansible config file
模組相關
A list of available modules
Playbooks
Using Ansible for configuration management & deployment
Mailing List
Questions? Help? Ideas? Stop by the list on Google Groups
irc.freenode.net
#ansible IRC chat channel