Страница 1 из 1

передача параметра в утилиту конвейером

Добавлено: 2009-07-09 12:13:39
initYs
Всем привет. Есть вопрос такого плана, боюсь, что он относится к базовым, но я пока так и не смог нарыть ответа.

Есть некая утилита (допустим ps) в нее надо передать параметр через конвейер. Есть ли стандартный метод передачи переменных через конвейер в софт который не имеет встроенной поддержки (может какая то системная переменная)?

Чтобы было понятнее что я хочу - поясню:
вот, есть например такая команда. Но необходимо убрать perl, а передавать параметр напрямую в ps.

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

find /proc -maxdepth 1 -type d -regex "/.+/[0-9]+" -printf %f\\n | perl -ne 'chomp; `ps -p $_ h -o pid` || print "the pid $_ is missing!\n"' 
Если использовать формы вида

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

ps h -o pid -p $( find /proc -maxdepth 1 -type d -regex "/.+/[0-9]+" -printf %f\\n ) 

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

ps h -o pid -p <<< echo $( find /tmp -maxdepth 1 -type d -regex "/.+/[0-9]+" -printf %f\\n )
то невозможно определить статус операции для каждого передаваемого параметра. Вобщем, это только иллюстрация вопроса - сам вопрос озвучен выше. :roll:

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-09 18:00:15
terminus
xargs

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

find /proc -maxdepth 1 -type d -regex "/.+/[0-9]+" -printf %f\\n | xargs ps

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-09 21:51:37
initYs
Спасибо, то что надо, но все равно проблема не решилась. )) Точнее вылезла другая, после find передается не каждый идентификатор процесса в ps, а списком "pid1 pid2...pidN", поэтому xargs (точнее ps) всегда возвращает 0 статус, даже если несколько процессов из списка он не может найти. Чего не происходит, если передавать поочередно, это по идеи можно было бы осуществить через -exec или -execdir, но они к сожалению не понимают сложных выражений. Так что придётся, видимо оставить как есть с использованием perlа, правда надо его еще чуток подкрутить. :crazy:

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-09 22:36:06
terminus
В качестве гуманитарной помощи:

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

#!/bin/sh
for STR in `find /proc -maxdepth 1 -type d -regex "/.+/[0-9]+" -printf %f\\n`
do
ps $STR

   if [ $? -ne 0 ]
   then
   echo "ps $STR vernul oshibku - ne znaju kak teper' dalshe zhit' voobshe :("
   else
   echo "vse ok"
   fi

done

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 2:41:16
Гость
у автора темы какой-то чересчур сложный пример (ну не знаю я /proc, gnu find, perl). Может он не в курсе, что find умеет простейший flow control?

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

$ find /proc \
  -maxdepth 1 \
  -type d \
  -regex "/.+/[0-9]+" \
  \( \
    -execdir ps -p {} -o pid \; \
    -or \
    -execdir echo "the pid {} is missing!" \; \
  \)
и что -exec (и -execdir) следуют ведут себя адекватно, если программа выходит со статусом > 0.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 2:47:27
Гость
да и xargs тоже управляем,

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

$ find... | xargs -I% sh -c 'ps -p % -o pid || echo "the pid % is missing!"'

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 8:20:59
initYs
ага, спсибо за уточнения и за помощь. Я действительно не был в курсе, только разбираюсь в bash-скриптинге. Сейчас буду пробовать :drinks:

upd. просто я тренируюсь в разных аспектах bash-скриптинга и пытаюсь разобраться в нюансах. Поэтому пытаюсь уложить задачу в однострочную команду.
Гость писал(а):у автора темы какой-то чересчур сложный пример (ну не знаю я /proc, gnu find, perl). Может он не в курсе, что find умеет простейший flow control?

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

$ find /proc \
  -maxdepth 1 \
  -type d \
  -regex "/.+/[0-9]+" \
  \( \
    -execdir ps -p {} -o pid \; \
    -or \
    -execdir echo "the pid {} is missing!" \; \
  \)
и что -exec (и -execdir) следуют ведут себя адекватно, если программа выходит со статусом > 0.
вся проблема в том, что возвращается при поиске на pid а ./pid, поэтому напрямую подставить нельзя {} в команду. Но в любом случае, есть на чем подумать дополнительно уже.

C xargs получилось все как хотел :good: Еще раз спасибо, за пищу для размышлений.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 8:56:51
initYs
И вопрос в догонку чтобы не плодить тем )) можно ли определить текущий pid для команды?
Что то вроде

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

find /proc -maxdepth 1 -type d -regex "/.+$PPID"  -printf "your pid is %f\\n" &
[1] 2872
$ your pid is 31679
$ echo $PPID
31679
то есть видно, что в таком виде возвращается pid текущей оболочки, а не самого процесса find.
Или пример еще проще - как увидеть pid команды echo, а не шела?

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

echo "my pid is $PPID"

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 11:31:05
Гость
initYs писал(а):upd. просто я тренируюсь в разных аспектах bash-скриптинга и пытаюсь разобраться в нюансах. Поэтому пытаюсь уложить задачу в однострочную команду.
если хочешь помощи, то старайся придерживаться поведения POSIX shell'а. На bash'е скрипты тут мало кто пишет. Если уж писать, то на zsh или python'е.
initYs писал(а):вся проблема в том, что возвращается при поиске на pid а ./pid, поэтому напрямую подставить нельзя {} в команду. Но в любом случае, есть на чем подумать дополнительно уже.
а ты ставил -execdir, а не -exec? на фряшном find'е {} - имя файла без пути и `./'

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 11:39:26
initYs
ну да пробовал, на RHEL

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

find --version
GNU find версии 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX
вывод поиска

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

find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
./14619
я неплохо знаю perl, на нем много чего и пишу/писал. Но хочется немного научиться адвансед программированию на шеле. Но без фанатизма, конечно. С питоном может позже попробую разобраться.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 11:53:15
Гость
btw, нафиг ты проходишь /proc с помощью find'а. Если будешь парсить вывод ps, то overhead будет меньше за счет меньше числа syscall'ов.
initYs писал(а):то есть видно, что в таком виде возвращается pid текущей оболочки, а не самого процесса find.
нет, PPID (parent pid) возвращает PID родителя оболочки, в коей запущен find. Сама оболочка - $$.
Вообще-то ты не можешь отдать процессу в argv его собственный PID предварительно не зарезервировав shell'ом этот самый PID. А так процесс может получить свой PID по getpid(2).
initYs писал(а):Или пример еще проще - как увидеть pid команды echo, а не шела?

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

echo "my pid is $PPID"
echo - встроенная команда в sh- и csh-подобных shell'ах. Конечно она имеет такой же PID, как и у shell'а.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 11:57:46
Гость
initYs писал(а):

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

find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
./14619

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

$ find -E /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
1694
Ы ;)

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:04:52
Гость
initYs писал(а):

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

find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
./14619
кстати, ты можешь убрать `./' впереди без вызова внешних программ (кроме shell'а) так

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

$ find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir sh -c 'f={}; echo ${f##*/}' \;

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:05:39
initYs
btw, нафиг ты проходишь /proc с помощью find'а. Если будешь парсить вывод ps, то overhead будет меньше за счет меньше числа syscall'ов.
тут весь прикол, чтобы получить перечень процессов из /proc и сравнить с теми что показывает ps. Если есть скрытые для ps процессы - показать.

Да с echo, я тормознул, конечно. Про передачу параметров - все верно, точно не смогу. Спасибо за разъяснения.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:07:12
initYs
Гость писал(а):
initYs писал(а):

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

find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
./14619

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

$ find -E /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
1694
Ы ;)

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

find -E /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir echo '{}' \;
find: неверный предикат `-E'
что за опция?
Гость писал(а):кстати, ты можешь убрать `./' впереди без вызова внешних программ (кроме shell'а) так

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

$ find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir sh -c 'f={}; echo ${f##*/}' \;

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

find /proc -maxdepth 1 -type d -regex "/.+$PPID" -execdir sh -c 'f={}; echo ${f##*/}' \;
sh: ./f=14619: Нет такого файла или каталога
хмм интересная конструкция, просто в шелле работает. Тут видимо затык в передача параметра через {}. попробую разобраться.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:21:27
Гость
initYs писал(а):что за опция?
заставляет -regex понимать расширенные регулярные выражения.
http://en.wikipedia.org/wiki/Regular_ex ... xpressions
initYs писал(а):тут весь прикол, чтобы получить перечень процессов из /proc и сравнить с теми что показывает ps. Если есть скрытые для ps процессы - показать.
а что в linux нет опции для ps, чтобы показывать скрытые процессы?
initYs писал(а):Про передачу параметров - все верно, точно не смогу.
хм, почему нет. Кто мешает сделать exec() и завладеть PID'ом родителя?

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

$ sh -c 'ps -lp $$'
  UID   PID  PPID CPU PRI NI   VSZ   RSS MWCHAN STAT  TT       TIME COMMAND
 1001 58682  1699   0  44  0  7012  1468 -      R+     5    0:00.00 ps -lp 58682
где sh -c 'ps -lp $$' == sh -c 'exec ps -lp $$'

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:43:13
initYs
Гость писал(а):заставляет -regex понимать расширенные регулярные выражения.
http://en.wikipedia.org/wiki/Regular_ex ... xpressions'
я чего спрашивал - у себя найти не смог, ни в help, ни в man. Возможно версии разные утилит.
Гость писал(а):а что в linux нет опции для ps, чтобы показывать скрытые процессы?'
ну дело ж не в этом, а в практике юзанья шелл-скриптинга.. Вот уже на получал столько инфы, что не успеваю переваривать )))
Гость писал(а): хм, почему нет. Кто мешает сделать exec() и завладеть PID'ом родителя?

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

$ sh -c 'ps -lp $$'
  UID   PID  PPID CPU PRI NI   VSZ   RSS MWCHAN STAT  TT       TIME COMMAND
 1001 58682  1699   0  44  0  7012  1468 -      R+     5    0:00.00 ps -lp 58682
где sh -c 'ps -lp $$' == sh -c 'exec ps -lp $$'
Ага, идея понятна. Спасибо, есть над чем подумать и о чем почитать более подробно.

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:54:58
Гость
initYs писал(а):я чего спрашивал - у себя найти не смог, ни в help, ни в man. Возможно версии разные утилит.
http://man.freebsd.org/find/1
http://netbsd.gw.com/cgi-bin/man-cgi?find+1
правда в OpenBSD ее почему-то нет. ;\
initYs писал(а):Ага, идея понятна. Спасибо, есть над чем подумать и о чем почитать более подробно.
короче вот ответ на изначальный вопрос

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

$ bash -c 'find /proc -maxdepth 1 -type d -regex "/.+$$" -printf "your pid is %f\\n"'
your pid is 71531
где 71531 - PID find'а

Re: передача параметра в утилиту конвейером

Добавлено: 2009-07-10 12:58:50
initYs
Гость писал(а):
initYs писал(а):я чего спрашивал - у себя найти не смог, ни в help, ни в man. Возможно версии разные утилит.
http://man.freebsd.org/find/1
http://netbsd.gw.com/cgi-bin/man-cgi?find+1
правда в OpenBSD ее почему-то нет. ;\
initYs писал(а):Ага, идея понятна. Спасибо, есть над чем подумать и о чем почитать более подробно.
короче вот ответ на изначальный вопрос

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

$ bash -c 'find /proc -maxdepth 1 -type d -regex "/.+$$" -printf "your pid is %f\\n"'
your pid is 71531
где 71531 - PID find'а
я уже понял, мерси! :drinks: