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

Программирование на sh, быть может немного про альтернативные языки
Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-09 12:13:39

Всем привет. Есть вопрос такого плана, боюсь, что он относится к базовым, но я пока так и не смог нарыть ответа.

Есть некая утилита (допустим 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:

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
terminus
майор
Сообщения: 2305
Зарегистрирован: 2007-10-29 11:27:35
Откуда: Рига

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

Непрочитанное сообщение terminus » 2009-07-09 18:00:15

xargs

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

find /proc -maxdepth 1 -type d -regex "/.+/[0-9]+" -printf %f\\n | xargs ps
Модель: AST-PM-105/0044; Тип: Универсальный, ремонтный; Название: Терминус; Род повреждения: Распад функций; Выводы: Сдать на слом.

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-09 21:51:37

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

Аватара пользователя
terminus
майор
Сообщения: 2305
Зарегистрирован: 2007-10-29 11:27:35
Откуда: Рига

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

Непрочитанное сообщение terminus » 2009-07-09 22:36:06

В качестве гуманитарной помощи:

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

#!/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
Модель: AST-PM-105/0044; Тип: Универсальный, ремонтный; Название: Терминус; Род повреждения: Распад функций; Выводы: Сдать на слом.

Гость
проходил мимо

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!"'

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 8:20:59

ага, спсибо за уточнения и за помощь. Я действительно не был в курсе, только разбираюсь в 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: Еще раз спасибо, за пищу для размышлений.

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 8:56:51

И вопрос в догонку чтобы не плодить тем )) можно ли определить текущий 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'е {} - имя файла без пути и `./'

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 11:39:26

ну да пробовал, на 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##*/}' \;

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 12:05:39

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

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

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 12:07:12

Гость писал(а):
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: Нет такого файла или каталога
хмм интересная конструкция, просто в шелле работает. Тут видимо затык в передача параметра через {}. попробую разобраться.
Последний раз редактировалось initYs 2009-07-10 12:22:06, всего редактировалось 1 раз.

Гость
проходил мимо

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 $$'

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 12:43:13

Гость писал(а):заставляет -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'а

Аватара пользователя
initYs
рядовой
Сообщения: 14
Зарегистрирован: 2009-07-09 11:07:07
Откуда: из мамы

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

Непрочитанное сообщение initYs » 2009-07-10 12:58:50

Гость писал(а):
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: