Я запускаю цикл while в bash, чтобы периодически удалять все «старые» файлы в каталоге (сохраняя только 100 самых новых файлов). Этот процесс выполняется в фоновом режиме:
((cd /tmp/test && while true; do ls -t | sed -e '1,100d' | xargs -I{} -d '\n' rm -R {}; sleep 1; done)&)
Как мне найти процесс этого процесса bash в ps
?
Задача состоит в том, что часть более крупного скрипта я хотел бы автоматически определять, запущен ли этот процесс, а если нет, я хотел бы его запустить.
[править / пояснение] Сохранение PID не является решением, потому что скрипт может выполняться несколько раз. Предполагается, что машина будет подготовлена к следующему процессу. Предполагается, что пользователь / разработчик может просто запустить его, чтобы убедиться, что все настроено. Если части условий уже выполнены, они будут пропущены. Большинство из того, что необходимо выполнить, - это идемпотентные команды. Это единственная команда, которую я пытаюсь сделать идемпотентной. Это промежуточный способ взлома до тех пор, пока у нас не будет надлежащей системы обеспечения.
Вместо этого использовать crontab
?
ps aux
должен отображать большинство процессов и строку, в которой они были запущены, чтобы вы могли найти то, что вам нужно. lsof
может показать еще немного, возможно, даже слишком много.
Если вам нужно создать что-то легкое для использования с grep, поместите это в файл, скажем, ~/my.cmd
, и запустите
bash --init-file my.cmd
или просто сделайте его работоспособным и запустите my.cmd
.
вы даже можете использовать setsid
для отсоединения от терминала, чтобы он всегда работал в фоновом режиме. Тогда просто
ps aux | grep "my.cmd"
должен идентифицировать его, если есть два совпадения (два попадания - одно для grep, другое для выполнения). Вы можете использовать | wc -l
и проверить, возвращает ли он 2.
Я предлагаю вам проверить crontab, хотя он кажется лучше подходит для того, что вы хотите в целом.
На самом деле это не работает. Потому что я не знаю, что искать. Для тестирования я запускал конвейер, как в OP на переднем плане (без ((
)&)
), и пытался grep для test
, while
и sleep
, только сон показывает что-то, но не весь конвейер. Вместо этого он показывает только peter 17128 0.0 0.0 7288 668 pts/23 S+ 13:58 0:00 sleep 1
. Итак, как мне узнать, правильный ли это sleep
, а не другой?
@ P.R Самый простой способ - поместить его в файл и запустить вызов bash, который будет его источником.
Один из способов - сделать что-то вроде вашего скрипта:
lock = "/tmp/${name}.lock"
if [ -f "${lock}" ];then
echo "already running. pid: $(cat "${lock}")"
exit 1
fi
trap rm "${lock}" 2>/dev/null;exit" 0 1 2 15
echo $$ > "${lock}"
Вместо удаления N самых старых файлов я бы предложил удалить файлы старше определенного возраста, например N дней, например:
N=5 # delete everything older than N days
find /tmp/test -ctime +"${N}"d -depth 1 -exec rm -r {} +
Это дает много преимуществ, например, возможность обрабатывать файлы с пробелами или другими нечетными символами в имени. Это также более предсказуемо, потому что если ваш процесс создает, скажем, 10000 файлов в / tmp / test, то удаление 100 оставит вам беспорядок или, наоборот, может удалить новые файлы, которые вы действительно хотели сохранить. Также обратите внимание, что если у вас есть новые файлы в старом каталоге, ваши новые файлы будут уничтожены. -depth 1
предотвращает удаление самого файла / tmp / test.
Если вы действительно хотите удалить самые старые N файлов, я бы сделал это в сценарии и назвал бы это как-то вроде thecleaner.py &
и поискал бы ps
для этого.
#! /usr/bin/env python
# -*- coding: UTF8 -*-
import os
import shutil
import time
secs = 5 # number of seconds to pause during each loop
N = 100 # delete this many of the oldest files
top = "/tmp/test" # remove N oldest files in this directory
while True:
paths = sorted(os.listdir(top), key=os.path.getctime)
oldest = paths[:N]
for path in oldest:
print("removing: {}".format(path))
if os.path.isfile(path):
os.remove(path)
else:
shutil.rmtree(path) # delete entire directory tree
time.sleep(secs)
В противном случае я не знаю никакого способа надежно найти заданную вами петлю.
Разве это не проблема XY. Просто сохраните фоновый идентификатор процесса.
( you command )&; pid_of_my_command=$?; pgrep $?
. Если вы хотите, чтобы запускался только один экземпляр скрипта, используйте flock.