Как найти процесс, обрабатывающий канал bash

Я запускаю цикл 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 не является решением, потому что скрипт может выполняться несколько раз. Предполагается, что машина будет подготовлена ​​к следующему процессу. Предполагается, что пользователь / разработчик может просто запустить его, чтобы убедиться, что все настроено. Если части условий уже выполнены, они будут пропущены. Большинство из того, что необходимо выполнить, - это идемпотентные команды. Это единственная команда, которую я пытаюсь сделать идемпотентной. Это промежуточный способ взлома до тех пор, пока у нас не будет надлежащей системы обеспечения.

Разве это не проблема XY. Просто сохраните фоновый идентификатор процесса. ( you command )&; pid_of_my_command=$?; pgrep $?. Если вы хотите, чтобы запускался только один экземпляр скрипта, используйте flock.

KamilCuk 10.08.2018 14:49

Вместо этого использовать crontab?

keithpjolley 10.08.2018 14:53
0
2
43
2

Ответы 2

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. 10.08.2018 14:59

@ P.R Самый простой способ - поместить его в файл и запустить вызов bash, который будет его источником.

kabanus 10.08.2018 15:06

Один из способов - сделать что-то вроде вашего скрипта:

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)

В противном случае я не знаю никакого способа надежно найти заданную вами петлю.

Другие вопросы по теме