Вы можете уточнить, что вы подразумеваете под "командной строкой"?
Барт
Мне просто интересно, есть ли специальная переменная доллара, которая содержит полную строку (командную строку), а не только имя скрипта и его аргументы
адский код
2
Что бы вы использовали для этого?
Кусалананда
9
@ shellcode вам не нужно знать, если вы находитесь в трубе для этого. Просто проверьте, является ли вывод TTY. [ -t 1 ]unix.stackexchange.com/a/401938/70524
Но интерактивная bashоболочка может использовать механизм истории и DEBUGловушку, чтобы «сообщить» командам, которые она выполняет, полную командную строку, частью которой они являются, через переменную среды:
Хотя это полезно, это работает только в Linux, но не в других Unixes
Скотт Эрл
2
Используя /proc/self/fd, вы можете увидеть, находитесь ли вы в конвейере, а также идентификатор для канала. Если вы выполняете /proc/\*/fdпоиск подходящего канала, вы можете найти PID другого конца канала. С помощью PID вы можете затем прочитать /proc/$PID/cmdlineи повторить процесс в своих файловых дескрипторах, чтобы найти, к чему он подключен.
$ cat | cat | cat &
$ ps
PID TTY TIME CMD6942 pts/1600:00:00 cat6943 pts/1600:00:00 cat6944 pts/1600:00:00 cat7201 pts/1600:00:00 ps20925 pts/1600:00:00 bash
$ ls -l /proc/6942/fd
lrwx------.1 tim tim 64Jul2419:590->/dev/pts/16
l-wx------.1 tim tim 64Jul2419:591->'pipe:[49581130]'
lrwx------.1 tim tim 64Jul2419:592->/dev/pts/16
$ ls -l /proc/6943/fd
lr-x------.1 tim tim 64Jul2419:590->'pipe:[49581130]'
l-wx------.1 tim tim 64Jul2419:591->'pipe:[49581132]'
lrwx------.1 tim tim 64Jul2419:592->/dev/pts/16
$ ls -l /proc/6944/fd
lr-x------.1 tim tim 64Jul2419:590->'pipe:[49581132]'
lrwx------.1 tim tim 64Jul2419:591->/dev/pts/16
lrwx------.1 tim tim 64Jul2419:592->/dev/pts/16
Также, если вам повезет, различные команды в конвейере получат последовательные идентификаторы PID, что сделает его немного проще.
На самом деле у меня нет сценария для этого, но я доказал концепцию.
Спасибо за ваши ответы. Я проверил разные вещи и пришел к следующему сценарию тестирования:
test.sh:
hist=`fc -nl -0`# remove leading and trailing whitespaces
hist="$(echo "${hist}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo "Command line from history: '$hist'"if[-t 1];then
echo "Direct output to TTY, no pipe involved."else
echo "No TTY, maybe a piped command."fiif[-p /dev/stdout ];then
echo "stdout is a pipe."else
echo "stdout is not a pipe."fi
readlink -e /proc/self/fd/1
rst=$?if[ $rst -eq 0];then
echo "Readlink test status okay, no pipe involved."else
echo "Readlink test status error $rst, maybe a piped command."fi
тесты:
$ ./test.sh test1Command line from history:'./test.sh test1'Direct output to TTY, no pipe involved.
stdout is not a pipe./dev/pts/3Readlink test status okay, no pipe involved.
$ ./test.sh test2 | catCommand line from history:'./test.sh test2 | cat'No TTY, maybe a piped command.
stdout is a pipe.Readlink test status error 1, maybe a piped command.
$ echo "another command before pipe doesn't matter"|./test.sh test3Command line from history:'echo "another command before pipe doesn't matter" | ./test.sh test3'
Direct output to TTY, no pipe involved.
stdout is not a pipe.
/dev/pts/3
Readlink test status okay, no pipe involved.
История командной строки работает только без Шебанга в верхней строке скрипта. Не знаю, будет ли это работать надежно и на других системах.
Я не смог подавить вывод из «readlink» (или «file», как предложено в Archemar), когда статус был успешным («/ dev / pts / 3»). Передача вывода в / dev / null или в переменную может привести к сбоям. Так что это не будет вариант для меня в сценарии.
Проверка TTY, о которой говорилось в muru, проста и, возможно, уже достаточна для некоторых случаев использования.
Редактировать: Моя заслуга в Mosvy, потому что вопрос был в том, как получить полную командную строку, а не просто определить, находится ли сценарий на конвейере. Мне нравится простая часть "fc -nl -0" в его ответе, потому что дальнейшая настройка системы не требуется. Это не 100-процентное решение, но это только для моего личного использования и, следовательно, достаточно. Спасибо всем остальным за вашу помощь.
Проверка TTY также может быть сделано для стандартного ввода: [ -t 0 ]. Таким образом, вы можете проверить, является ли stdin или stdout TTY и действовать соответствующим образом.
Муру
Если вы хотите узнать, является ли stdout каналом, в Linux вы можете использовать его if [ -p /dev/stdout ]; ...(точно так же, как readlink /proc/self/fd/..это не работает в BSD).
Мосви
2
Скрипт нуждается в работе ИМНШО. echo -eпочти наверняка не хочет -e. Вам нужно больше тестов, перенаправляющих в файл, вызываемых внутри $(...). Однако я призываю вас подумать, если это хорошая идея. Программы, lsкоторые меняют свой вывод в зависимости от того, выводят ли они на tty или канал, раздражают.
[ -t 1 ]
unix.stackexchange.com/a/401938/70524Ответы:
Там нет никакого способа сделать это в целом .
Но интерактивная
bash
оболочка может использовать механизм истории иDEBUG
ловушку, чтобы «сообщить» командам, которые она выполняет, полную командную строку, частью которой они являются, через переменную среды:источник
нет
bash (или ваша оболочка) выполнит две разные команды.
test.sh arg1
grep "xyz"
test.sh
не мог знать о следующем grep.однако вы можете узнать, что находитесь «внутри» трубы, протестировав
/proc/self/fd/1
test.sh
который работает как
(Изменить) см . Комментарий Муру о том, что вы знаете, находитесь ли вы на трубе.
источник
Используя
/proc/self/fd
, вы можете увидеть, находитесь ли вы в конвейере, а также идентификатор для канала. Если вы выполняете/proc/\*/fd
поиск подходящего канала, вы можете найти PID другого конца канала. С помощью PID вы можете затем прочитать/proc/$PID/cmdline
и повторить процесс в своих файловых дескрипторах, чтобы найти, к чему он подключен.Также, если вам повезет, различные команды в конвейере получат последовательные идентификаторы PID, что сделает его немного проще.
На самом деле у меня нет сценария для этого, но я доказал концепцию.
источник
Другим способом может быть доступ к
$BASH_COMMAND
автоматической переменной, но она по своей природе нестабильна и трудно уловить требуемое значение.Я думаю, что вы можете поймать его только через an
eval
, который также включает специальный вызов ваших командных строк, например:Здесь
$BASH_COMMAND
расширяется, а также очищается доeval
строки, и результирующая строка, таким образом, «снимается» в вспомогательную$CMD
переменную.Маленький пример:
Естественно, он также может работать (на самом деле лучше) при вызове скриптов, например,
sh -c
илиbash -c
, как в:Здесь без очистки переменной.
источник
Спасибо за ваши ответы. Я проверил разные вещи и пришел к следующему сценарию тестирования:
test.sh:
тесты:
История командной строки работает только без Шебанга в верхней строке скрипта. Не знаю, будет ли это работать надежно и на других системах.
Я не смог подавить вывод из «readlink» (или «file», как предложено в Archemar), когда статус был успешным («/ dev / pts / 3»). Передача вывода в / dev / null или в переменную может привести к сбоям. Так что это не будет вариант для меня в сценарии.
Проверка TTY, о которой говорилось в muru, проста и, возможно, уже достаточна для некоторых случаев использования.
Редактировать: Моя заслуга в Mosvy, потому что вопрос был в том, как получить полную командную строку, а не просто определить, находится ли сценарий на конвейере. Мне нравится простая часть "fc -nl -0" в его ответе, потому что дальнейшая настройка системы не требуется. Это не 100-процентное решение, но это только для моего личного использования и, следовательно, достаточно. Спасибо всем остальным за вашу помощь.
источник
[ -t 0 ]
. Таким образом, вы можете проверить, является ли stdin или stdout TTY и действовать соответствующим образом.if [ -p /dev/stdout ]; ...
(точно так же, какreadlink /proc/self/fd/..
это не работает в BSD).echo -e
почти наверняка не хочет-e
. Вам нужно больше тестов, перенаправляющих в файл, вызываемых внутри$(...)
. Однако я призываю вас подумать, если это хорошая идея. Программы,ls
которые меняют свой вывод в зависимости от того, выводят ли они на tty или канал, раздражают.