Как проверить, является ли оболочка логином / интерактивной / пакетной

145

Я думаю, что я понимаю разницу между интерактивом, логином и пакетной оболочкой. Смотрите следующие ссылки для получения дополнительной помощи:

У меня вопрос, как я могу проверить с командой / условием, если я нахожусь в интерактивном режиме, входе в систему или пакетной оболочке?

Я ищу команду или условие (которое возвращает trueили false) и которое я мог бы также поместить в оператор if. Например:

if [[ condition ]]
   echo "This is a login shell"
fi
Амелио Васкес-Рейна
источник
3
Есть еще один вопрос: подключены ли STDIN и / или STDOUT к tty (терминалу) или каналу (файлу или процессу)? Это связанный, но отличный тест, описанный в некоторых комментариях ниже.
Марк Хадсон

Ответы:

162

Я предполагаю bashоболочку или что-то подобное, поскольку в тегах нет оболочки.

Чтобы проверить, находитесь ли вы в интерактивной оболочке:

[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'

Чтобы проверить, находитесь ли вы в оболочке входа в систему:

shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'

Под «пакетным» я предполагаю, что вы имеете в виду «не интерактивный», поэтому проверки на наличие интерактивной оболочки должно быть достаточно.

Крис Даун
источник
12
Для zshпользователей проверка входа в оболочку может быть выполнена с помощью:if [[ -o login ]] ...
chb
1
Если вы хотите узнать, запускал ли ваша программа вашу программу, а не «cron». [[TERM == "тупой"]] && echo "Запуск в cron.
Эрик Аронести
10
@ErikAronesty Не все тупые терминалы являются cron-сессиями.
Крис Даун
2
«Я предполагаю, что это оболочка bash или что-то подобное, поскольку в тегах нет никакой оболочки». - Логика этого утверждения действительно прекрасна! :)
Михаэль Ле Барбье Грюневальд
2
@antonio Это потому, что ваше цитирование неверно, $-расширяется в текущей оболочке. Если вы используете одинарные кавычки вокруг полного выражения, вы получите правильный результат:bash -c '[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"'
Крис Даун
34

В любой оболочке в стиле Борна iпараметр указывает, является ли оболочка интерактивной:

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This is a script";;
esac

Не существует портативного и полностью надежного способа тестирования оболочки входа. Кш и зш добавить lв $-. Bash устанавливает login_shellопцию, с которой вы можете запросить shopt -q login_shell. В частности, проверьте, $0начинается ли с -: shells, как правило, известно, что они являются оболочками входа в систему, потому что вызывающая сторона добавила -префикс к нулевому аргументу (обычно это имя или путь исполняемого файла). Это не в состоянии обнаружить специфические для оболочки способы вызова оболочки входа (например ash -l).

жилль
источник
(...) потому что звонящий - я думаю, что-то не хватает в этом фрагменте.
Петр Доброгост
Было бы идеально, если бы все начиналось $0с того, с чего -бы это ни началось. Но есть по крайней мере одно исключение: это не всегда верно для bash, даже если предполагается, что это оболочка для входа. Попробуйте это в своей коробке: вызовите bash --login, затем $0все еще читает bash.
Wirawan Purwanto
@WirawanPurwanto Я не уверен, что понимаю ваш комментарий. Разве это не то, что я написал в моем последнем предложении?
Жиль
@ Жиль: Вы правы. Извините, я пропустил ваше последнее предложение.
Wirawan Purwanto
24

ракушка

Вот ответ на fishслучай, если другие пользователи наткнуться на эту страницу.

if status --is-interactive
    # ...
end

if status --is-login
    # ...
end

echo "darn, I really wanted to have to use globs or at least a case statement"

Рыбная документация: инициализация

ohspite
источник
1
-1 за ненужную редакцию.
Ник Бастин
6
Если кто-то задается вопросом в комментарии @ NickBastin, у него была справедливая точка зрения, поэтому я сделал правку. Оригинальное количество саркастики теперь было сокращено вдвое.
ohspite
18

csh / tcsh

Для cshи у tcshменя есть следующее в моем .cshrcфайле:

if($?prompt) then               # Only interactive shells set $prompt
    ...
endif

Специально для tcshпеременной loginshустанавливается для оболочки входа в систему:

if($?loginsh) then              # A login shell..
    ...
endif

( tcshтакже есть переменная, shlvlкоторая установлена ​​в число вложенных оболочек, где оболочка входа в систему имеет значение 1.)

Эндрю Стейн
источник
2
PS1не работает для проверки интерактивной оболочки. Он почти всегда устанавливается в интерактивном режиме, но вы можете отключить его. Это очень часто устанавливает в неинтерактивной оболочке, так как многие системы корабля с export PSв /etc/profile.
Жиль
@ Жиль Спасибо за исправление и редактирование
Эндрю Стейн
17

Другой способ - проверить результат tty

if [ "`tty`" != "not a tty" ]; then
Адриан Корниш
источник
10
... или используйте [ -t 0 ]для проверки, является ли STDIN tty. Вы также можете использовать 1 (STDOUT) или 2 (STDERR) в зависимости от ваших потребностей.
Дероберт
@derobert - спасибо, что показали мне что-то новое
Адриан Корниш
10
Это другой тест. Возможно иметь неинтерактивную оболочку, вход которой является терминалом (каждый раз, когда вы запускаете скрипт в терминале!), И возможно (хотя и редко) иметь интерактивную оболочку, принимающую ввод не из терминала.
Жиль
@ Жиль, если оболочка была интерактивной и закрытой, оставляя ребенка disownживым, ttyлучше всего было знать, что она больше не интерактивна, но $-не изменилась; Я все еще озадачен тем, что является лучшим подходом.
Водолей Сила
5
@AquariusPower Тогда вы хотите протестировать не интерактивную оболочку, а стандартный терминал ввода. Используйте [ -t 0 ]. PS В своем предыдущем комментарии я написал, что «существует сильная корреляция» - я забыл «кроме очень распространенного случая сценария, начинающегося с #!/bin/shили тому подобного», который не является интерактивным, но может быть подключен к терминалу.
Жиль
8

UNIX / Linux имеет команду, чтобы проверить, если вы находитесь на терминале.

if tty -s
then
echo Terminal
else
echo Not on a terminal
fi
Павел
источник
1
Это работает dashтакже.
Кен Шарп
7

Вы можете проверить, является ли stdin терминалом:

if [ -t 0 ]
then
    echo "Hit enter"
    read ans
fi
Angelo
источник
3

Чтобы проверить, выполняется ли сценарий в интерактивной или неинтерактивной оболочке, я проверяю в своих сценариях наличие приглашения, хранящегося в $PS1переменной:

if [ -z $PS1 ] # no prompt?
### if [ -v PS1 ]   # On Bash 4.2+ ...
then
  # non-interactive
  ...
else
  # interactive
  ...
fi

Об этом я узнал здесь: https://www.tldp.org/LDP/abs/html/intandnonint.html

Кристиан Херенц
источник
1

iне правильный вариант для поиска. -iзаставить неинтерактивную оболочку стать интерактивной. Правильная опция автоматического включения есть -s, но, к сожалению, Bash не справляется с этим правильно.

Вам нужно проверить, $-содержит ли s(это разрешено для автоматической активации) или содержит ли он i(это не разрешено для автоматической активации, но официально подключено только к параметру -iкомандной строки оболочки).

Шили
источник
1
sбыло бы, если оболочка читает команды из стандартного ввода, а не является ли он интерактивным. Интерактивная оболочка не обязательно читает команды из stdin (попробуйте zsh -i < /dev/null, хотя zsh кажется здесь исключением). И оболочка может читать команды из stdin и не быть интерактивной (как sh < fileили echo 'echo "$1"' | sh -s foo bar).
Стефан Шазелас
2
Я хотел бы отметить, что в оригинальной оболочке Bourne Shell нет символа «i» в $, даже если он предназначен для интерактивной работы.
Шил
Хорошо, но в U & L «оболочка», как правило, относится к современным оболочкам. Оболочка Bourne, как правило, считается повторной, и ваш собственный вариант не достаточно распространен, чтобы ожидать, что люди будут знать, о чем вы говорите, если вы не сделаете это явно. Упомянутый вопрос [[...]]подразумевает ksh / bash / zsh. У вас есть пункт как история записка , что проверка iин $-не будет работать в оболочке Bourne. Но тогда проверка на sнадежность там тоже не сработает. Вы хотели бы также проверить [ -t 0 ]или i; даже тогда это было бы одурачено в угловых случаях, таких какecho 'exec < /dev/tty; that-check' | sh'
Стефан Шазелас
Solaris вплоть до Solaris 10 поставляется с оригинальной оболочкой Bourne Shell, и даже подоконник включает aprox. 10 ошибок, как известно, в оболочке начиная с SVr4. Таким образом, добавление подсказки к Bourne Shell не является хитрой шляпой, как вы могли бы поверить. С другой стороны, zsh недостаточно совместим, например, происходит сбой при попытке запустить «configure» с zsh, поэтому будьте осторожны, чтобы настроить / bin / sh, чтобы он указывал на zsh. Кстати, мой Bourne Shell устанавливает -i по умолчанию, если решает, что он будет интерактивным.
Шили
3
Я заметил, что POSIX, кажется, не требует $ - содержат i (что, кажется, требует s), я подниму вопрос о ML группы Austin.
Стефан Шазелас