Julio Fernandez
Julio Fernandez

Reputation: 265

How to kill a running process using ansible?

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 processes
  shell: "ps -ef | grep -v grep | grep -w {{ PROCESS }} | awk '{print $2}'"
  register: running_processes

- name: Kill running processes
  shell: "kill {{ item }}"
  with_items: "{{ running_processes.stdout_lines }}"

- name: Waiting until all running processes are killed
  wait_for:
    path: "/proc/{{ item }}/status"
    state: absent
  with_items: "{{ running_processes.stdout_lines }}"

Thanks!

Upvotes: 25

Views: 71090

Answers (5)

Manohar Shetty
Manohar Shetty

Reputation: 1

This Code Worked for me

- hosts: ubuntu
  become: yes
  tasks:
  - name: Get Apache PIDs
    shell:
      cmd: ps -ef | grep -v grep | grep -w apache2 | awk '{print $2}' | awk 'FNR == 1 {print}'
      warn: false
    changed_when: false
    check_mode: false
    register: apache_pids

  - name: Kill running processes
    shell: "kill {{ item }}"
    with_items:
    - "{{ apache_pids.stdout_lines }}"

  - name: Show PIDs
    debug:
      var: apache_pids

Upvotes: 0

nean
nean

Reputation: 51

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: PROCESS
    enabled: no
    state: stopped
  tags:
    - stop

- name: "evaluate running PROCESS processes from remote host"
  command: "/usr/bin/pgrep PROCESS"
  register: running_PROCESS
  failed_when: running_PROCESS.rc > 1
  changed_when: 
    - running_PROCESS.rc == 0
  tags:
    - stop

- name: "pkill PROCESS running processes"
  command: "/usr/bin/pkill PROCESS"
  register: kill_PROCESS
  changed_when: kill_PROCESS.rc == 0
  when: running_PROCESS.stdout_lines | length > 0
  tags:
    - stop

- name: "check PROCESS processes"
  wait_for:
    path: "/proc/{{ item }}/status"
    state: absent
  with_items: "{{ running_PROCESS.stdout_lines }}"
  when: running_PROCESS.stdout_lines | length > 0
  tags:
    - stop

- name: "force kill stuck PROCESS processes"
  command: "/usr/bin/pkill -9 PROCESS"
  register: kill9_PROCESS
  changed_when: kill9_PROCESS.rc == 0
  failed_when: kill9_PROCESS.rc > 1
  when:
    - running_PROCESS.stdout_lines | length > 0
  tags:
    - stop

Upvotes: 4

Tobias Ernst
Tobias Ernst

Reputation: 4644

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.

Upvotes: 5

Sean
Sean

Reputation: 10206

Use pkill(1) instead of grep+kill.

Upvotes: 6

Eric Citaire
Eric Citaire

Reputation: 4513

You could ignore errors on wait_for and register the result to force kill failed items:

- name: Get running processes
  shell: "ps -ef | grep -v grep | grep -w {{ PROCESS }} | awk '{print $2}'"
  register: running_processes

- name: Kill running processes
  shell: "kill {{ item }}"
  with_items: "{{ running_processes.stdout_lines }}"

- wait_for:
    path: "/proc/{{ item }}/status"
    state: absent
  with_items: "{{ running_processes.stdout_lines }}"
  ignore_errors: yes
  register: killed_processes

- name: Force kill stuck processes
  shell: "kill -9 {{ item }}"
  with_items: "{{ killed_processes.results | select('failed') | map(attribute='item') | list }}"

Upvotes: 65

Related Questions