可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I would like to quickly monitor some hosts using commands like ps,dstat etc using ansible-playbook. The ansible
command itself perfectly does what I want, for instance I'd use:
ansible -m shell -a "ps -eo pcpu,user,args | sort -r -k1 | head -n5"
and it nicely prints all std output for every host like this:
localhost | success | rc=0 >>
0.0 root /sbin/init
0.0 root [kthreadd]
0.0 root [ksoftirqd/0]
0.0 root [migration/0]
otherhost | success | rc=0 >>
0.0 root /sbin/init
0.0 root [kthreadd]
0.0 root [ksoftirqd/0]
0.0 root [migration/0]
However this requires me to keep a bunch of shell scripts around for every task which is not very 'ansible' so I put this in a playbook:
---
-
hosts: all
gather_facts: no
tasks:
- shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
and run it with -vv
, but the output baiscally shows the dictionary content and newlines are not printed as such so this results in an unreadable mess like this:
changed: [localhost] => {"changed": true, "cmd": "ps -eo pcpu,user,args | sort -r -k1
head -n5 ", "delta": "0:00:00.015337", "end": "2013-12-13 10:57:25.680708", "rc": 0,
"start": "2013-12-13 10:57:25.665371", "stderr": "", "stdout": "47.3 xxx Xvnc4 :24
-desktop xxx:24 (xxx) -auth /home/xxx/.Xauthority -geometry 1920x1200\n
....
I also tried adding register: var
and the a 'debug' task to show {{ var.stdout }}
but the result is of course the same.
Is there a way to get nicely formatted output from a command's stdout/stderr when run via a playbook? I can think of a number of possible ways (format output using sed? redirect output to file on the host then get that file back and echo it to the screen?), but with my limited knowledge of the shell/ansible it would take me a day to just try it out.
回答1:
The debug
module could really use some love, but at the moment the best you can do is use this:
- hosts: all
gather_facts: no
tasks:
- shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
register: ps
- debug: var=ps.stdout_lines
It gives an output like this:
ok: [host1] => {
"ps.stdout_lines": [
"%CPU USER COMMAND",
" 1.0 root /usr/bin/python",
" 0.6 root sshd: root@notty ",
" 0.2 root java",
" 0.0 root sort -r -k1"
]
}
ok: [host2] => {
"ps.stdout_lines": [
"%CPU USER COMMAND",
" 4.0 root /usr/bin/python",
" 0.6 root sshd: root@notty ",
" 0.1 root java",
" 0.0 root sort -r -k1"
]
}
回答2:
This is a start may be :
- hosts: all
gather_facts: no
tasks:
- shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
register: ps
- local_action: command echo item
with_items: ps.stdout_lines
NOTE: Docs regarding ps.stdout_lines
are covered here: ('Register Variables' chapter).
回答3:
Expanding on what leucos said in his answer, you can also print information with Ansible's humble debug
module:
- hosts: all
gather_facts: no
tasks:
- shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
register: ps
# Print the shell task's stdout.
- debug: msg={{ ps.stdout }}
# Print all contents of the shell task's output.
- debug: var=ps
回答4:
If you need a specific exit status, Ansible provides a way to do that via callback plugins.
Example. It's a very good option if you need a 100% accurate exit status.
If not, you can always use the Debug Module, which is the standard for this cases of use.
Cheers
回答5:
I found using the minimal stdout_callback
with ansible-playbook gave similar output to using ad-hoc ansible.
In your ansible.cfg (Note that I'm on OS X so modify the callback_plugins
path to suit your install)
stdout_callback = minimal
callback_plugins = /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/ansible/plugins/callback
So that a ansible-playbook
task like yours
---
-
hosts: example
gather_facts: no
tasks:
- shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
Gives output like this, like an ad-hoc command would
example | SUCCESS | rc=0 >>
%CPU USER COMMAND
0.2 root sshd: root@pts/3
0.1 root /usr/sbin/CROND -n
0.0 root [xfs-reclaim/vda]
0.0 root [xfs_mru_cache]
I'm using ansible-playbook 2.2.1.0
回答6:
ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook /tmp/foo.yml -vvv
Tasks with STDOUT will then have a section:
STDOUT:
What ever was in STDOUT
回答7:
Perhaps not relevant if you're looking to do this ONLY using ansible. But it's much easier for me to have a function in my .bash_profile
and then run _check_machine host1 host2
function _check_machine() {
echo 'hostname,num_physical_procs,cores_per_procs,memory,Gen,RH Release,bios_hp_power_profile,bios_intel_qpi_link_power_management,bios_hp_power_regulator,bios_idle_power_state,bios_memory_speed,'
hostlist=$1
for h in `echo $hostlist | sed 's/ /\n/g'`;
do
echo $h | grep -qE '[a-zA-Z]'
[ $? -ne 0 ] && h=plabb$h
echo -n $h,
ssh root@$h 'grep "^physical id" /proc/cpuinfo | sort -u | wc -l; grep "^cpu cores" /proc/cpuinfo |sort -u | awk "{print \$4}"; awk "{print \$2/1024/1024; exit 0}" /proc/meminfo; /usr/sbin/dmidecode | grep "Product Name"; cat /etc/redhat-release; /etc/facter/bios_facts.sh;' | sed 's/Red at Enterprise Linux Server release //g; s/.*=//g; s/\tProduct Name: ProLiant BL460c //g; s/-//g' | sed 's/Red Hat Enterprise Linux Server release //g; s/.*=//g; s/\tProduct Name: ProLiant BL460c //g; s/-//g' | tr "\n" ","
echo ''
done
}
E.g.
$ _machine_info '10 20 1036'
hostname,num_physical_procs,cores_per_procs,memory,Gen,RH Release,bios_hp_power_profile,bios_intel_qpi_link_power_management,bios_hp_power_regulator,bios_idle_power_state,bios_memory_speed,
plabb10,2,4,47.1629,G6,5.11 (Tikanga),Maximum_Performance,Disabled,HP_Static_High_Performance_Mode,No_CStates,1333MHz_Maximum,
plabb20,2,4,47.1229,G6,6.6 (Santiago),Maximum_Performance,Disabled,HP_Static_High_Performance_Mode,No_CStates,1333MHz_Maximum,
plabb1036,2,12,189.12,Gen8,6.6 (Santiago),Custom,Disabled,HP_Static_High_Performance_Mode,No_CStates,1333MHz_Maximum,
$
Needless to say function won't work for you as it is. You need to update it appropriately.