bash и поиск процессов (нужно проверить не запущен ли уже этот скрипт)

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Ответить
Atheist
Сообщения: 63

bash и поиск процессов

Сообщение Atheist »

вобщем такая задача:
есть баш-скрипт, передающий файлы. он запускается по крону к примеру раз в час.
так вот если файлов много, то он за час не успеет их передать, но тем не менее его новая копия все-равно по крону запуститься и у меня получится уже 2 работающих скрипта.

Хочу встроить в скрипт проверку, которая будет закрывать новую копию, если старая еще не завершилась.

в голову приходят 2 варианта:
1 - лок-файл
2 - список процессов.

С лок-файлом не супер решение как мне кажется, а вдруг скрипт глюкнет и лок-файл останется (не удалиться после завершения рабоыт скрипта), тогда новя копия его никогда не запутиться.

Со списком процессов вроде как-то надежнее. вот что придумал:

Код: Выделить всё

#!/bin/bash
echo $$
ps -ef | grep  $(basename $0)

этот скрипт мне выдает вот такое:

Код: Выделить всё

kspus@stalin:/opt/ftproot> ./test.sh
32125
kspus    32125 31548  0 15:47 pts/3    00:00:00 /bin/bash ./test.sh
kspus    32127 32125  0 15:47 pts/3    00:00:00 /bin/bash ./test.sh
kspus    32128 32127  0 15:47 pts/3    00:00:00 basename ./test.sh

kspus@stalin:/opt/ftproot> ./test.sh
32129
kspus    32129 31548  0 15:47 pts/3    00:00:00 /bin/bash ./test.sh
kspus    32131 32129  0 15:47 pts/3    00:00:00 /bin/bash ./test.sh
kspus    32132 32131  0 15:47 pts/3    00:00:00 /bin/bash ./test.sh

kspus@stalin:/opt/ftproot> ./test.sh
32133
kspus    32133 31548  0 15:47 pts/3    00:00:00 /bin/bash ./test.sh
kspus    32135 32133  0 15:47 pts/3    00:00:00 grep test.sh

что-то как-то это не очень блин: то basename то grep то вообще непойми что вылазит....
Может кто уже решал такую задачку?
Спасибо сказали:
Аватара пользователя
vr13
Сообщения: 876
ОС: gentoo

Re: bash и поиск процессов

Сообщение vr13 »

в аналогичных скриптах (и даже в некоторых демонах) обычно делается так: скрипт пишет "лок"-файл в котором указывается свой pid. запускаемая копия проверяет "лок", если таковой имеется, проверятся наличие в системе процесса с таким pid. можно проверить еще командную строку

следует заметить, что все проверки достаточно условны - если задаться целью можно придумать ситауцию когда они не сработают. поэтому если критично можно усложнить. в целом до бесконечности, когда "програмимизм" увлечет. решение всегда компромисно :)
Спасибо сказали:
Atheist
Сообщения: 63

Re: bash и поиск процессов

Сообщение Atheist »

ну про лок-файл я писал, мне кажется что решение основанное на имени процесса более надежное, и не сильно сложнее..
не пойму отчего баш выдает разные результаты - не успевает или еще чего??
Как можно добиться стабильности?
Спасибо сказали:
reinhard
Сообщения: 86
ОС: Fedora Core, FreeBSD

Re: bash и поиск процессов

Сообщение reinhard »

Atheist писал(а):
10.07.2007 16:36
ну про лок-файл я писал, мне кажется что решение основанное на имени процесса более надежное, и не сильно сложнее..
не пойму отчего баш выдает разные результаты - не успевает или еще чего??
Как можно добиться стабильности?


Код: Выделить всё

ps -ef | grep $(basename $0) | grep -v grep | grep -v basename


Но вариант с лок-файлом мне больше нравится.

Код: Выделить всё

PIDFILE=/var/run/process.pid
[ -f $PIDFILE ] && kill -0 `cat $PIDFILE` && ps -p `cat $PIDFILE` -o cmd | grep `basename $0` >/dev/null && exit 2
rm -f $PIDFILE
Спасибо сказали:
Atheist
Сообщения: 63

Re: bash и поиск процессов

Сообщение Atheist »

Код: Выделить всё

PIDFILE=/var/run/process.pid
[ -f $PIDFILE ] && kill -0 `cat $PIDFILE` && ps -p `cat $PIDFILE` -o cmd | grep `basename $0` >/dev/null && exit 2
rm -f $PIDFILE

А можете пояснить чего тут написано, а то я в одну строку сложно это воспринимаю

И в догонку еще вопросец:
Есть файл "secon dfile.txt"
в него к примеру идет запись (открыт).
Как мне увидеть его имя?
делаю вот так - куча лишней инфы:

Код: Выделить всё

kspus@stalin:/opt/ftproot> lsof | grep /opt/ftproot/in
cat       11122      kspus    1w      REG  147,0      256    939140 /opt/ftproot/in/secon dfile.txt


делаю вот так - отрезает имя:

Код: Выделить всё

kspus@stalin:/opt/ftproot> lsof | grep /opt/ftproot/in | awk '{print $9}'
/opt/ftproot/in/secon

делаю вот так - вроде все ОК, однако если фалй будет называться "src ond fil e.txt" то у мнея опять отрежет имя, можно конечно ...print $9,$10,$11,$12,$13 и так до 100, но это как то коряво :)

Код: Выделить всё

 kspus@stalin:/opt/ftproot> lsof | grep /opt/ftproot/in | awk '{print $9,$10}'
/opt/ftproot/in/secon dfile.txt
Спасибо сказали:
reinhard
Сообщения: 86
ОС: Fedora Core, FreeBSD

Re: bash и поиск процессов

Сообщение reinhard »

Atheist писал(а):
11.07.2007 09:29
А можете пояснить чего тут написано, а то я в одну строку сложно это воспринимаю


Код: Выделить всё

[ -f $PIDFILE ]
- если есть $PIDFILE

Код: Выделить всё

&& kill -0 `cat $PIDFILE`
и существует процесс, PID которога записан в $PIDFILE

Код: Выделить всё

&& ps -p `cat $PIDFILE` -o cmd | grep `basename $0` >/dev/null
и если команда этого процесса совпадает с basename нашего процесса

Код: Выделить всё

&& exit 2
- выходим

Код: Выделить всё

rm -f $PIDFILE
echo $$ >$PIDFILE

в противном случае удаляем $PIDFILE и записываем туда pid нашего процесса.

И в догонку еще вопросец:
Есть файл "secon dfile.txt"
в него к примеру идет запись (открыт).
Как мне увидеть его имя?
делаю вот так - куча лишней инфы:

Код: Выделить всё

kspus@stalin:/opt/ftproot> lsof | grep /opt/ftproot/in
cat       11122      kspus    1w      REG  147,0      256    939140 /opt/ftproot/in/secon dfile.txt


Мне больше нравится решить эту задачу перлом и его Regular Expression:

Код: Выделить всё

lsof | grep /opt/ftproot/in | perl -e '$_=<STDIN>;/\d\s+(\/.+)$/;print "$1\n";'


Возможно, есть более элегантное решение.
Спасибо сказали:
Atheist
Сообщения: 63

Re: bash и поиск процессов

Сообщение Atheist »

reinhard - спасибо, разжевал :)
в таком варианте проверка действительно надежна!

у меня тогда еще вопрос:
этот же скрипт обрабатывает файлы, поступающие в определенную директоию (по фтп, смб, ссш). обрабатывает он их по крону.
так во - может случиться так. что к примеру файл еще не скопировали полностью (большой он или канал дохлый) - а скрипт уже начал его обрабатывать: копировать. переименовывать и так далее.
Мне подсказали что можно посмотреть список открытых файлов и отбросить те, которые в настоящий момент окрыты (то есть еще не докачались):

Код: Выделить всё

lsof | grep /opt/ftproot | grep dbf | awk '{print $9}'

вот так мне выдаются имена открытых файлов (если они без пробелов - но это другой вопрос:))

однако в таком виде показываются файлы только того пользователя, который запустил lsof, и к тому же если файл льется по ссш - то его тоже не видно (то ли кусками льется толи фиг его знает) - вобщем иногда видно что он открыт и ногда нет...

Кто может подсказать как мне отбросить файлы, которые в настоящий момент открыты
Спасибо сказали:
Atheist
Сообщения: 63

Re: bash и поиск процессов

Сообщение Atheist »

А что за опция такая -0 у kill?

Код: Выделить всё

kspus@stalin:/opt/ftproot> kill -0 `cat test.lock`
-bash: kill: (14819) - Нет такого процесса
kspus@stalin:/opt/ftproot>


kspus@stalin:/opt/ftproot> ./test.sh
./test.sh: line 7: [: -0: binary operator expected
kspus@stalin:/opt/ftproot>


kspus@stalin:/opt/ftproot> cat test.sh
#!/bin/bash
LOCK_FILE=test.lock
MY_PID=$$
if [ -f $LOCK_FILE ] && [ kill -0 `cat $LOCK_FILE` ] && [ ps -p `cat $LOCK_FILE` -o cmd | grep `basename $0` ]
then
    errlogw "ERROR: Файл $LOCK_FILE существует. Возможно выполняется другая копия скрипта. Работа прекращается!"
    exit 2
else
    rm -f $LOCK_FILE
    echo $MY_PID > $LOCK_FILE
fikspus@stalin:/opt/ftproot>
Спасибо сказали:
reinhard
Сообщения: 86
ОС: Fedora Core, FreeBSD

Re: bash и поиск процессов

Сообщение reinhard »

Atheist писал(а):
12.07.2007 10:43
А что за опция такая -0 у kill?


Послать процессу 0 сигнал, на который он не реагирует никак.
Практически способ узнать есть ли процесс с таким PID.

Код: Выделить всё

kspus@stalin:/opt/ftproot> kill -0 `cat test.lock`
-bash: kill: (14819) - Нет такого процесса


Чтобы избежать сообщения "Нет такого процесса" надо перенаправить вывод ошибок в /dev/null

Код: Выделить всё

kill -0 `cat test.lock` 2>/dev/null


Код: Выделить всё

kspus@stalin:/opt/ftproot> cat test.sh
#!/bin/bash
LOCK_FILE=test.lock
MY_PID=$$
if [ -f $LOCK_FILE ] && [ kill -0 `cat $LOCK_FILE` ] && [ ps -p `cat $LOCK_FILE` -o cmd | grep `basename $0` ]


Вот здесь
[ kill -0 `cat $LOCK_FILE` ]
квадратные скобочки лишние.
Спасибо сказали:
reinhard
Сообщения: 86
ОС: Fedora Core, FreeBSD

Re: bash и поиск процессов

Сообщение reinhard »

Atheist писал(а):
12.07.2007 09:48
у меня тогда еще вопрос:
этот же скрипт обрабатывает файлы, поступающие в определенную директоию (по фтп, смб, ссш). обрабатывает он их по крону.
так во - может случиться так. что к примеру файл еще не скопировали полностью (большой он или канал дохлый) - а скрипт уже начал его обрабатывать: копировать. переименовывать и так далее.
Мне подсказали что можно посмотреть список открытых файлов и отбросить те, которые в настоящий момент окрыты (то есть еще не докачались):

Код: Выделить всё

lsof | grep /opt/ftproot | grep dbf | awk '{print $9}'

вот так мне выдаются имена открытых файлов (если они без пробелов - но это другой вопрос:))

однако в таком виде показываются файлы только того пользователя, который запустил lsof, и к тому же если файл льется по ссш - то его тоже не видно (то ли кусками льется толи фиг его знает) - вобщем иногда видно что он открыт и ногда нет...

Кто может подсказать как мне отбросить файлы, которые в настоящий момент открыты


Ну тут несколько вариантов...
Если lsof запускать от рута, он покажет все открытые файлы.
Можно делать секундный sleep и смотреть не изменился ли размер.
Если есть возможность, обязать тех, кто льет файлы после закачки выкладывать файл размером 1 байт с суффиксом .check, например.
В FreeBSD попробовать kqueue ;-)
Ну и другие варианты...
Спасибо сказали:
Atheist
Сообщения: 63

Re: bash и поиск процессов

Сообщение Atheist »

reinhard писал(а):
12.07.2007 14:42
Вот здесь
[ kill -0 `cat $LOCK_FILE` ]
квадратные скобочки лишние.

убрал скобочки там везде и поставил двойные:

Код: Выделить всё

./test.sh: line 5: conditional binary operator expected
./test.sh: line 5: syntax error near `-0'
./test.sh: line 5: `if [[ -f $LOCK_FILE  &&  kill -0 `cat $LOCK_FILE`  &&  ps -p `cat $LOCK_FILE` -o cmd | grep `basename $0` ]]'
Спасибо сказали:
Аватара пользователя
BuGfiX
Сообщения: 78
ОС: slackware-current
Контактная информация:

Re: bash и поиск процессов

Сообщение BuGfiX »

Позвольте спросить, а чем /usr/bin/pgrep не угодил? Зачем такие извраты?
Спасибо сказали:
reinhard
Сообщения: 86
ОС: Fedora Core, FreeBSD

Re: bash и поиск процессов

Сообщение reinhard »

Atheist писал(а):
12.07.2007 14:58
reinhard писал(а):
12.07.2007 14:42
Вот здесь
[ kill -0 `cat $LOCK_FILE` ]
квадратные скобочки лишние.

убрал скобочки там везде и поставил двойные:

Код: Выделить всё

./test.sh: line 5: conditional binary operator expected
./test.sh: line 5: syntax error near `-0'
./test.sh: line 5: `if [[ -f $LOCK_FILE  &&  kill -0 `cat $LOCK_FILE`  &&  ps -p `cat $LOCK_FILE` -o cmd | grep `basename $0` ]]'



после if не обязательно ставить двойные скобки.
Да и if тут совсем необязателен.
Правильная конструкция, если хочешь использовать if:

Код: Выделить всё

if  [ -f $LOCK_FILE ] && kill -0 `cat $LOCK_FILE` && ps -p `cat $LOCK_FILE` -o cmd | grep `basename $0`
then exit 2;
else echo $$ >$LOCK_FILE
fi


BuGfiX писал(а):
12.07.2007 16:33
Позвольте спросить, а чем /usr/bin/pgrep не угодил? Зачем такие извраты?


Я просто не знал о таком :-)
Спасибо сказали:
Ответить