Проверьте, был ли скрипт bash запущен из оболочки или другого скрипта / приложения - PullRequest
11 голосов
/ 24 ноября 2010

Я пишу скрипт bash, чтобы перенаправить вывод другой команды в нужное место. По сути, когда скрипт вызывается из командной строки или оболочки, я хочу отправить вывод в STDOUT. Но когда bash-скрипт выполняется из какого-то другого приложения (например, из другого bash-скрипта, из другого приложения или, в моем случае, из плагина awesome-prompt в моем Awesome Window Manager), я хочу перенаправить вывод куда-то еще.

Есть ли способ в bash увидеть, как был вызван скрипт?

Ответы [ 4 ]

21 голосов
/ 24 ноября 2010

Попробуйте это:

ps -o stat= -p $PPID

Если результат содержит «s» (нижний регистр), он был запущен из командной строки или задан внутри скрипта.Чтобы разделить эти две части:

ps -o stat= -p $$

будет содержать "+", если он не был задним фоном.

Вот таблица:

Run          $$    $PPID
CL           S+    Ss
CL&          S     Ss+
Script       S+    S+
Script&      S     S
Script(&)    S     Ss
Script&(&)   S     NULL

Где (&)означает, что дочерний сценарий был фоновым, и & означает, что родительский сценарий (на который ссылается «Скрипт»), который выполнял его, был фоновым.CL означает командную строку.NULL означает, что ps выводит ноль, а $PPID равно "1".

From man ps:

   s    is a session leader
   +    is in the foreground process group

Следует отметить, что этот ответ основан на GNU ps, но справочные страницы для BSD (включая OS X) указывают на схожую функциональность.А GNU ps - это гибрид, который включает в себя, помимо прочего, функциональность BSD.

8 голосов
/ 24 ноября 2010

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

if [[ -t 1 ]]; then
        echo "Terminal"
else
        echo "Not-a-terminal"
fi

Вышеприведенная команда [[ -t 1 ]] проверяет, является ли дескриптор файла 1 (т.е. стандартный вывод) терминалом или нет.

РЕДАКТИРОВАТЬ:

Обратите внимание, что это будет указывать на нетерминальное stdout, если вы передадите вывод какой-либо другой программе.В этом случае вам может потребоваться более универсальное условие, которое также проверит стандартный ввод (дескриптор файла 0):

[[ -t 0 || -t 1 ]]
1 голос
/ 09 марта 2012

Эту функцию я адаптировал из другого поста на эту тему.Он сопоставляет все родительские процессы до вершины с элементами, перечисленными в переменной $shells.Когда это сделано, $iscli устанавливается в 0 или 1. Если он установлен в 0, то вы знаете, что он был запущен из оболочки или того, что вы считаете достаточно для этой цели.Если установлено значение 1, то вы знаете, что была задействована программа, которая не утверждена.Я использую это для сценариев, которые я хочу запускать в оболочке и через PHP, когда я хочу, чтобы каждый вывод был разным* иметь значение.

function top_level_parent_pid {

    scriptname="${0##*/}"
    shells="^bash|^init|^screen|^sh|^ssh|^su|${scriptname}"

    pid=${1:-$$}
    pidname="`ps --no-heading -o %c -p ${pid}`"
    stat=($(</proc/${pid}/stat))
    ppid=${stat[3]}
    ppidname="`ps --no-heading -o %c -p ${ppid}`"
    isclitest="`echo "${ppidname}" | grep -iv -E "${shells}"`"

    until [ "${ppid}" -eq "1" ] || [ "${iscli}" = "1" ]; do

            if [[ -n "${isclitest}" ]]; then

                    iscli="1"

                 else

                    iscli="0"


                    top_level_parent_pid ${ppid}
            fi
    done
}
0 голосов
/ 24 ноября 2010

Вы можете использовать $ PPID

Что-то вроде

  PARENT=`ps --no-heading -o %c -p $PPID`
  echo $PARENT

Это установит в переменной PARENT имя процесса родителя, а затем выведет его на экран.

Затем вы можете поместить некоторые операторы if на основе значения $ PARENT

НТН

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...