I have an ansible playbook to kill running processes and works great most of the time!, however, from time to time we find processes that just can't be killed so, "wait_for" gets to the timeout, throws an error and it stops the process.
The current workaround is to manually go into the box, use "kill -9" and run the ansible playbook again so I was wondering if there is any way to handle this scenario from ansible itself?, I mean, I don't want to use kill -9 from the beginning but I maybe a way to handle the timeout?, even to use kill -9 only if process hasn't been killed in 300 seconds? but what would be the best way to do it?
These are the tasks I currently have:
- name: Get running processesshell: "ps -ef | grep -v grep | grep -w {{ PROCESS }} | awk '{print $2}'"register: running_processes- name: Kill running processesshell: "kill {{ item }}"with_items: "{{ running_processes.stdout_lines }}"- name: Waiting until all running processes are killedwait_for:path: "/proc/{{ item }}/status"state: absentwith_items: "{{ running_processes.stdout_lines }}"
Thanks!
Best Answer
You could ignore errors on wait_for
and register the result to force kill failed items:
- name: Get running processesshell: "ps -ef | grep -v grep | grep -w {{ PROCESS }} | awk '{print $2}'"register: running_processes- name: Kill running processesshell: "kill {{ item }}"with_items: "{{ running_processes.stdout_lines }}"- wait_for:path: "/proc/{{ item }}/status"state: absentwith_items: "{{ running_processes.stdout_lines }}"ignore_errors: yesregister: killed_processes- name: Force kill stuck processesshell: "kill -9 {{ item }}"with_items: "{{ killed_processes.results | select('failed') | map(attribute='item') | list }}"
Use pkill
(1) instead of grep
+kill
.
The killall
command has a wait option that might be useful.
Install psmisc:
tasks:- apt: pkg=psmisc state=present
Then use killall like this:
tasks:- shell: "killall screen --wait"ignore_errors: true # In case there is no process
-w, --wait
:Wait for all killed processes to die. killall checks once per second if any of the killed processes still exist and only returns if none are left.
After some investigations and struggling with ansible_linter
, below an alternative way (eg. without use of ignore_error
)
- name: "disable and stop PROCESS"service:name: PROCESSenabled: nostate: stoppedtags:- stop- name: "evaluate running PROCESS processes from remote host"command: "/usr/bin/pgrep PROCESS"register: running_PROCESSfailed_when: running_PROCESS.rc > 1changed_when: - running_PROCESS.rc == 0tags:- stop- name: "pkill PROCESS running processes"command: "/usr/bin/pkill PROCESS"register: kill_PROCESSchanged_when: kill_PROCESS.rc == 0when: running_PROCESS.stdout_lines | length > 0tags:- stop- name: "check PROCESS processes"wait_for:path: "/proc/{{ item }}/status"state: absentwith_items: "{{ running_PROCESS.stdout_lines }}"when: running_PROCESS.stdout_lines | length > 0tags:- stop- name: "force kill stuck PROCESS processes"command: "/usr/bin/pkill -9 PROCESS"register: kill9_PROCESSchanged_when: kill9_PROCESS.rc == 0failed_when: kill9_PROCESS.rc > 1when:- running_PROCESS.stdout_lines | length > 0tags:- stop
This Code Worked for me
- hosts: ubuntubecome: yestasks:- name: Get Apache PIDsshell:cmd: ps -ef | grep -v grep | grep -w apache2 | awk '{print $2}' | awk 'FNR == 1 {print}'warn: falsechanged_when: falsecheck_mode: falseregister: apache_pids- name: Kill running processesshell: "kill {{ item }}"with_items:- "{{ apache_pids.stdout_lines }}"- name: Show PIDsdebug:var: apache_pids