Tohle je naprosto typická situace. Nafasujete do týmu juniorního kolegu a ten dostane nápad promazat někde logy. A samozřejmě smaže i ty log soubory, do kterých právě zapisují aplikace, čímž nedojde k uvolnění file desriptorů a proto nedojde k uvolnění jediného kilobajtu místa navíc.
Tak pánové pro vás tu sem hodím oneliner, který to udělá za vás, ať už to nikdy nikomu nemusím znovu vysvětlovat. 😉
A víte co je na tomhle nejvtipnější? Zeptáte se na to ChatGPT, i google Gemini a ani jeden z nich vám nedokáže poradit.
for files in $(find /proc/*/fd -ls | grep '(deleted)' | awk '{print $11}'); do > $files ; done
Nicméně jestli jsou na něco ChatGPT či Google Gemini, anebo další modely dobré, je předělání tohoto příkazu do ansible playbooku vč. komentářů :
- name: Vyčištění diskového prostoru - smazané, ale otevřené soubory
hosts: your_target_hosts # Zde nahraďte názvem vaší skupiny hostů nebo IP adresou
become: yes # Spustí tasky s oprávněním root (sudo)
tasks:
- name: Najít cesty ke smazaným, ale stále otevřeným souborům
ansible.builtin.shell: |
# Používáme $NF (last field) pro robustnější extrakci cesty k souboru
# Přesměrování 2>/dev/null potlačí chyby přístupu k /proc/<PID>/fd, které se mohou objevit
find /proc/*/fd -ls 2>/dev/null | grep '(deleted)' | awk '{print $NF}'
register: deleted_fds_output # Uloží výstup příkazu do proměnné
changed_when: false # Tento task pouze vyhledává, nic nemění, takže ho neoznačujeme jako "změněný"
- name: Vynulovat obsah smazaných souborů držených procesy
ansible.builtin.shell: |
# Vynulování souboru pomocí přesměrování ">"
> {{ item }}
loop: "{{ deleted_fds_output.stdout_lines }}" # Prochází každý řádek z výstupu předchozího tasku
when: deleted_fds_output.stdout_lines is defined and deleted_fds_output.stdout_lines | length > 0
# Podmínka 'when' zajistí, že se loop spustí, jen pokud byly nějaké soubory nalezeny.
# Můžete přidat 'ignore_errors: yes', pokud nechcete, aby playbook selhal,
# pokud se některý soubor nepodaří vynulovat (např. kvůli race condition).
Ještě pro pořádek vám sem vložím tento příkaz:
lsof |grep deleted
A až nebudete vědět, co který sloupec znamená, tak sem uvedu i záhlaví výstupu příkazu:
COMMAND PID TID TASKCMD USER FD TYPE DEVICE SIZE/OFF NODE NAME
a uvedu sem zdroj na článek o lsof, zdroj2,