Как я могу узнать из сценария оболочки, что оболочка, которая его вызывала, является интерактивной оболочкой? - PullRequest
1 голос
/ 13 июля 2010

Я пытаюсь настроить скрипт оболочки, который начнет сеанс screen (или присоединится к существующему), только если он вызывается из интерактивной оболочки. Решение, которое я видел, состоит в том, чтобы проверить, содержит ли $- букву «i»:

#!/bin/sh -e

echo "Testing interactivity..."
echo 'Current value of $- = '"$-"
if [ `echo \$- | grep -qs i` ]; then
  echo interactive;
else
  echo noninteractive;
fi

Однако это не удается, поскольку скрипт запускается новой неинтерактивной оболочкой, которая вызывается в результате #!/bin/sh вверху. Если я использую сценарий вместо его запуска, он будет работать, как хотелось бы, но это ужасный хак. Я предпочел бы, чтобы это работало, когда я запускаю его.

Так, как я могу проверить интерактивность в скрипте?

Ответы [ 6 ]

1 голос
/ 22 июля 2010

$_ может не работать в каждом POSIX-совместимом sh, хотя, вероятно, он работает в обязательном порядке.

$PS1 будет установлен, только если оболочка является интерактивной.Так что это должно работать:

if [ -z "$PS1" ]; then
    echo noninteractive
else
    echo interactive
fi
1 голос
/ 13 июля 2010

Попробуйте и посмотрите, выполняет ли он то, что вы ищете:

#!/bin/sh
if [ $_ != $0 ]
then
  echo interactive;
else
  echo noninteractive;
fi

Подчеркивание ($_) расширяется до абсолютного пути, используемого для вызова скрипта. Ноль ($0) расширяется до имени скрипта. Если они отличаются, то скрипт вызывается из интерактивной оболочки. В Bash последующее расширение $_ дает расширенный аргумент предыдущей команде (возможно, было бы неплохо сохранить значение $_ в другой переменной для его сохранения).

С man bash:

   0      Expands to the name of the shell or shell script.  This  is  set
          at shell initialization.  If bash is invoked with a file of com‐
          mands, $0 is set to the name of that file.  If bash  is  started
          with  the  -c option, then $0 is set to the first argument after
          the string to be executed, if one is present.  Otherwise, it  is
          set  to  the file name used to invoke bash, as given by argument
          zero.
   _      At shell startup, set to the absolute pathname  used  to  invoke
          the  shell or shell script being executed as passed in the envi‐
          ronment or argument list.  Subsequently,  expands  to  the  last
          argument  to the previous command, after expansion.  Also set to
          the full pathname used  to  invoke  each  command  executed  and
          placed in the environment exported to that command.  When check‐
          ing mail, this parameter holds the name of the  mail  file  cur‐
          rently being checked.
0 голосов
/ 01 октября 2013

Если вы хотите проверить значение $- без разветвления внешнего процесса (например, grep), тогда вы можете использовать следующую технику:

if [ "${-%i*}" != "$-" ]
then
    echo Interactive shell
else
    echo Not an interactive shell
fi

При этом удаляется любое совпадение для i* из значения $-, а затем проверяется, имеет ли это какое-либо значение.


(конструкция ${parameter/from/to} (например, [ "${-//[!i]/}" = "i" ] является истинной, если она интерактивна) может использоваться в скриптах Bash, но отсутствует в Dash, который /bin/sh в системах Debian и Ubuntu.)

0 голосов
/ 01 октября 2013

Простой ответ: не запускайте эти команды внутри `` или [ ].

Здесь нет необходимости ни для одной из этих конструкций.


Очевидно, я не могу быть уверен, что вы ожидаете, что

[ `echo \$- | grep -qs i` ]

будет тестировать, но я не думаю, что он тестирует то, что вы думаете, тестирует.

Этот код сделаетследующее:

  • Выполнить echo \$- | grep -qs i внутри подоболочки (из-за ``).
  • Захватить стандартный вывод подоболочки.
  • Заменить оригинальное выражение ``со строкой, содержащей этот вывод.
  • Передайте эту строку в качестве аргумента в команду [ или встроенную (в зависимости от вашей оболочки).
  • Создайте успешный код возврата из [ только если эта строка была непустой (при условии, что строка не выглядела как опция [).

Некоторые возможные проблемы:

  • -qsопции grep должны привести к тому, что он не будет выводить, поэтому я ожидаю, что [ будет тестировать пустую строку независимо от того,как выглядит $-.
  • Также возможно, что обратный слеш экранирует знак доллара и приводит к тому, что буквенный «доллар минус» (а не содержимое переменной) отправляется на grep.

С другой стороны, если вы убрали [ и галочки и вместо этого сказали

if echo "$-" | grep -qs i ; then

, тогда:

  • ваш текущийshell расширит "$-" значением, которое вы хотите проверить,
  • echo ... | отправит его на grep на своем стандартном входе,
  • grep вернет успешный код возвратаесли этот ввод содержал букву i,
  • grep не выводил бы выходные данные из-за флагов -qs, а
  • оператор if использовал бы grep 's код возврата, чтобы решить, какую ветвь взять.

Также:

  • никакие обратные помехи не заменят любые команды с выводом, полученным при их запуске, и

Подробнее о том, как использовать команду if, см. этот раздел отличный БашГид.

0 голосов
/ 16 июля 2010

Вы можете попробовать использовать что-то вроде ...

if [[ -t 0 ]]
then
     echo "Interactive...say something!"
     read line
echo $line
else
     echo "Not Interactive"
fi

Переключатель "-t" в поле теста проверяет, совпадает ли указанный дескриптор файла с терминалом (вы также можете сделать это, чтобы остановить программуесли вывод собирался распечатать, например, на терминал).Здесь он проверяет, соответствует ли стандарт в программе терминалу.

0 голосов
/ 14 июля 2010

попробуй tty

if tty 2>&1 |grep not ; then echo "Not a tty"; else echo "a tty"; fi

man tty: Утилита tty записывает имя терминала, привязанное к стандарту ввод в стандартный вывод. Имя, которое написано, является строкой возвращается по ttyname (3). Если стандартный вход не является терминалом, сообщение `` не tty '' написано.

...