Выход из терминала после запуска скрипта bash
Я пытаюсь написать bash
скрипт для открытия определенных файлов (в основном PDF-файлов) с помощью gnome-open
команда. Я также хочу, чтобы терминал завершил работу после открытия файла PDF.
Я пробовал добавлять exit
до конца моего сценария, однако, что не закрывает терминал. Я пытался найти в Интернете ответ на свой вопрос, но не смог найти подходящий, я был бы очень признателен, если бы вы, ребята, могли помочь.
Мне нужен ответ, который убивает только терминал, с которого я запускаю команду, не все терминалы это было бы возможно? Предыдущий ответ, который я принял, убивает все открытые окна терминала. Я не осознавал, что это имело место до сегодняшнего дня.
8 ответов
Если вы открываете только один файл, вам на самом деле не нужно использовать сценарий, потому что сценарий предназначен для простого выполнения нескольких команд подряд, в то время как здесь вам просто нужно выполнить две команды (включая exit
).
Если вы хотите запустить exit
после команды или после цепочки команд вы можете связать ее с тем, что у вас уже есть, используя &&
оператор (который при успешном выполнении предыдущей команды / цепочки команд выполнит следующую команду) или с помощью ;
оператор (который как при успешном, так и при неудачном завершении предыдущей команды / цепочки команд выполнит следующую команду).
В этом случае это будет что-то вроде этого:
gnome-open <path_to_pdf_file> && exit
*
exit
положить в конец сценария не работает, потому что он просто выходит из bash
экземпляр, в котором выполняется скрипт, который является другим bash
экземпляр, чем внутренний терминал bash
пример.
Если вы хотите использовать скрипт в любом случае, самый простой способ - просто вызвать скрипт так:
<path_to_script> && exit
Или, если скрипт находится в текущем рабочем каталоге Терминала, вот так:
./<script> && exit
Если вы действительно не хотите / не можете этого сделать, второй самый простой способ - добавить эту строку в конец вашего скрипта:
kill -9 $PPID
Это отправит SIGKILL
сигнал к родительскому процессу сценария (bash
экземпляр связан с Терминалом). Если бы только один bash
Экземпляр связан с Терминалом, и его уничтожение заставит Терминал закрыться. Если несколько bash
экземпляры связаны с Терминалом, что уничтожение не приведет к закрытию Терминала.
Ты можешь использовать exec ./your-script
,
Эмулятор терминала, такой как GNOME Terminal, завершает работу, когда завершается начальный процесс, выполняющийся внутри него - обычно это оболочка.
Если вы уже находитесь в терминале и единственное, что вы хотите сделать перед выходом из этого терминала, это запустить определенный скрипт (или программу), то это означает, что вам больше не нужна оболочка, которая в нем работает. Таким образом, вы можете использовать оболочку exec
встроенный, чтобы заставить оболочку заменить себя процессом, созданным вашей командой.
- В случае вашего сценария это еще один процесс оболочки - так же, как создается второй процесс оболочки при запуске сценария без
exec
,
Синтаксис exec command
например, exec ./your-script
,
exec
: пример
Например, предположим, у меня есть сценарий оболочки count
, отмечен исполняемым файлом и находится в текущем каталоге. Это содержит:
#!/usr/bin/env bash
for i in {5..1}; do echo $i; sleep 1; done
И в терминале я запускаю:
exec ./count
Это печатает цифры 5
, 4
, 3
, 2
, а также 1
, один раз в секунду, а затем окно терминала закрывается.
Если вы запустите это из чего-то другого, чем первый процесс, запущенный в вашем терминале - например, если вы запустили bash
сначала запустить другой экземпляр оболочки, а затем вы вернетесь к оболочке, которая создала этот процесс, а не к выходу из терминала. (Это предостережение относится в равной степени к exit
методы.)
Ты можешь использовать ./your-script; exit
,
Если вы не хотите указывать своей оболочке заменять себя новым процессом (через exec
), вы можете сказать, чтобы он оставался, но прекратил работу сразу после завершения нового процесса.
Для этого запустите вашу команду и exit
команда, разделенная ;
поэтому их можно указывать в одной строке.
Синтаксис command; exit
например, ./your-script; exit
,
command; exit
против command && exit
Вы можете заметить, что это похоже на ./your-script && exit
метод, предложенный в ответах Коса и Химейла. Разница в том, что:
&&
запускает вторую команду только в том случае, если первая команда сообщила, что ей это удалось, вернув нулевой код завершения.;
запускает вторую команду независимо от того, сообщила ли первая команда об успешном выполнении.
Какой вы хотите, зависит от конкретной ситуации. Если команда не выполняется, вы хотите, чтобы вызывающая оболочка (и хост-терминал) продолжали работать? Если так, используйте &&
; если нет, используйте ;
,
Существует также command || exit
, который выходит из вызывающей оболочки, только если command
сообщили о неудаче.
Этот скрипт завершает работу терминала и, следовательно, оболочки и самого себя.
Это беспощадно убивает все процессы. Если в терминале открыто несколько вкладок, они также закрыты.
Проблема в том, что если открыто несколько терминалов, а это дочерние процессы gnome-terminal-server
все терминалы будут убиты.
В этом случае скрипт должен быть запущен в независимом терминале, например xterm
<your_command> & disown
PPPID=$(awk '{print $4}' "/proc/$PPID/stat")
kill $PPPID
PPID
PPID - это идентификатор родительского процесса, в этом случае оболочка (
e.g. /bin/bash
)PPPID
PPPID - это идентификатор родительского процесса PPID, в данном случае это окно терминала.
<your_command> & disown
В оболочке bash встроенная команда disown используется для удаления заданий из таблицы заданий или для пометки заданий, чтобы сигнал SIGHUP не отправлялся им, если родительская оболочка его получает (например, если пользователь выходит из системы).
awk '{print $4}' "/proc/$PPID/stat"
Получает значение четвертого столбца файла
/proc/$PPID/stat
(например, для/proc/1/stat
возвращается 0)
Вы можете использовать свой скрипт вместо того, чтобы его запустить, например
$ cat run.sh
exit;
$ ./run.sh #will not close
$ . ./run.sh # will close
Лично я выполнил бы команду, чтобы открыть pdf или другие файлы в подоболочке, отложил задержку, чтобы открыть файлы, и затем завершил работу. В основном вот что я проверял (nohup gnome-open *.pdf &); sleep 2; exit
Вариация на это будет nohup gnome-open *.pdf && sleep 2 && exit
Чтобы явно ответить на заглавный вопрос,
"Выход из терминала после запуска bash-скрипта":
Запускай только свой скрипт в терминале
Не глядя на детали того, что делает скрипт, скрипт может быть запущен непосредственно в терминале с опцией -e
(--command
), без запуска оболочки - она используется вместо оболочки тогда:
gnome-terminal -e ./script.sh
Используйте опцию -x
(--execute
) когда вы хотите предоставить аргументы скрипту. При этом только вся остальная часть командной строки принимается в качестве команды и аргументов.
gnome-terminal -x ./script.sh foo bar
Если ваш скрипт завершается, нет никакой интерактивной оболочки, которая могла бы задержать что-либо, ожидая пользовательского ввода.
Примеры
Теминал просто выйдет после того, как запущенная в нем команда завершится - вот так, закрыв после sleep
пробежал 4 секунды без оболочки:
gnome-terminal -x sleep 4
Конечно, вы можете по-прежнему использовать сценарии оболочки, потому что в любом случае ваш сценарий использует другой экземпляр оболочки.
Кроме того, вы можете запустить оболочку с явным сценарием - она не будет интерактивной:
gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
Самое простое решение было бы:
xdg-open file.pdf && exit
В отличие от других подобных команд nohup
не нужно, чтобы команда игнорировала SIGHUP
причина в том, xdg-open
закроет порождение дочернего процесса, который является предпочтительным приложением для открытия файла PDF. Поскольку фактический процесс, запущенный из терминала, больше не подлежит уничтожению, nohup
не нужен
&&
указывает на то, что следующая команда будет выполнена, если предыдущая команда была успешной, т.е. возвращает код выхода 0
($?=0
) а также exit
просто закроет терминал.
С «Когда скрипт завершает работу, закройте терминал» в настройках терминала, я помещаю это внизу исполняемого скрипта bash, чтобы закрыть его:
echo "Automatically Closing in 3 seconds..."
sleep 3
exit
read # show terminal output
Когда я ставлю выход после чтения, скрипт и окно терминала не закрываются.
Еще один приятный способ, который я часто использую для перезагрузки скрипта из его начальной точки в том же терминале:
echo "Enter = Restart"
echo "Ctrl+c or Close button to Close"
read
exec bash "$0" "$@" # Restart script from the beginning
Здесь правило перезапуска следует за «чтением».
Cheerio.