Después del cambio
python opt/project1/Table_Control.py opt/project1/connection.yaml >> /tmp/2.log 2>&1
En el registro, encontré un error. Python no encontró el módulo de Python de solicitudes.
Cambié
python opt/project1/Table_Control.py opt/project1/connection.yaml >> /tmp/2.log 2>&1
a
/data/Anaconda2-4.4.0/envs/python36/bin/python opt/project1/Table_Control.py opt/project1/connection.yaml >> Table_Control.log >&1
p.d.
Ahora funcionó bien, PERO no entendí por qué si ejecuto desde el script de shell -sin errores,PERO si la ejecución desde el trabajo cron devolvió el error, no se encontraron solicitudes del módulo python...
Нет способа сделать это вообще .
Но интерактивная bash
оболочка может использовать механизм истории и ловушку DEBUG
, чтобы «информировать» команды, которые она запускает, о полной командной строке, частью которой они являются, через переменную среды:
$ trap 'export LC=$(fc -nl -0); LC=${LC#? }' DEBUG
$ sh -c 'printf "last_command={%s}\n" "$LC"' | cat; true
last_command={sh -c 'printf "last_command={%s}\n" "$LC"' | cat; true}
Спасибо за ответы. Я тестировал разные вещи и пришел к следующему тестовому сценарию:
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."
fi
if [ -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 test1
Command line from history: './test.sh test1'
Direct output to TTY, no pipe involved.
stdout is not a pipe.
/dev/pts/3
Readlink test status okay, no pipe involved.
$./test.sh test2 | cat
Command 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 test3
Command 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 или в переменную приведет к неисправности. Так что это не вариант для меня в сценарии.
Проверка телетайпа, о которой упоминал муру, проста и, возможно, уже достаточна для некоторых случаев использования.
Редактировать :Моя заслуга mosvy, потому что вопрос был в том, как получить полную командную строку, а не только определить, находится ли скрипт на трубе. я люблю простая часть «fc -nl -0» в его ответе, потому что дальнейшая настройка системы не требуется. Это не 100-процентное решение, но это только для моего личного использования и поэтому достаточно. Спасибо всем остальным за вашу помощь.
Другим способом может быть доступ к автоматической переменной $BASH_COMMAND
, но она по своей природе изменчива и трудно получить требуемое значение.
Я думаю, что вы могли бы поймать это только через eval
, что также включает в себя вызов ваших командных строк -особым образом, как в:
CMD="${BASH_COMMAND##* eval }" eval './test.sh arg1 | grep "xyz"'
Здесь $BASH_COMMAND
расширяется, а также очищается до eval
бита строки, и результирующая строка, таким образом, "снимается" во вспомогательную переменную $CMD
.
Маленький пример:
$ cat test.sh
#!/bin/sh
printf 'you are running %s\n' "$CMD"
sleep 1
echo bye bye
$
$ CMD="${BASH_COMMAND##* eval }" eval './test.sh | { grep -nH "."; }'
(standard input):1:you are running './test.sh | { grep -nH "."; }'
(standard input):2:bye bye
$
Естественно, он также может работать (на самом деле лучше )при вызове скриптов, например. sh -c
или bash -c
, как в:
$
$ CMD="${BASH_COMMAND}" sh -c './test.sh | { grep -nH "."; }'
(standard input):1:you are running CMD="${BASH_COMMAND}" sh -c './test.sh | { grep -nH "."; }'
(standard input):2:bye bye
$
Здесь без очистки переменной.
Используя /proc/self/fd
, вы можете увидеть, находитесь ли вы в конвейере, а также идентификатор канала. Если вы выполните итерацию по /proc/\*/fd
в поисках соответствующего канала, вы сможете найти PID другого конца канала. С PID вы можете затем прочитать /proc/$PID/cmdline
, а также повторить процесс на его файловых дескрипторах, чтобы найти, во что он передан.
$ cat | cat | cat &
$ ps
PID TTY TIME CMD
6942 pts/16 00:00:00 cat
6943 pts/16 00:00:00 cat
6944 pts/16 00:00:00 cat
7201 pts/16 00:00:00 ps
20925 pts/16 00:00:00 bash
$ ls -l /proc/6942/fd
lrwx------. 1 tim tim 64 Jul 24 19:59 0 -> /dev/pts/16
l-wx------. 1 tim tim 64 Jul 24 19:59 1 -> 'pipe:[49581130]'
lrwx------. 1 tim tim 64 Jul 24 19:59 2 -> /dev/pts/16
$ ls -l /proc/6943/fd
lr-x------. 1 tim tim 64 Jul 24 19:59 0 -> 'pipe:[49581130]'
l-wx------. 1 tim tim 64 Jul 24 19:59 1 -> 'pipe:[49581132]'
lrwx------. 1 tim tim 64 Jul 24 19:59 2 -> /dev/pts/16
$ ls -l /proc/6944/fd
lr-x------. 1 tim tim 64 Jul 24 19:59 0 -> 'pipe:[49581132]'
lrwx------. 1 tim tim 64 Jul 24 19:59 1 -> /dev/pts/16
lrwx------. 1 tim tim 64 Jul 24 19:59 2 -> /dev/pts/16
Кроме того, если вам повезет, разные команды в конвейере получат последовательные идентификаторы PID, что немного упростит задачу.
На самом деле у меня нет сценария для этого, но я доказал концепцию.