Как найти процесс, обрабатывающий канал 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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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)

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

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