Выход из терминала после запуска скрипта bash

Я пытаюсь написать bash скрипт для открытия определенных файлов (в основном PDF-файлов) с помощью gnome-open команда. Я также хочу, чтобы терминал завершил работу после открытия файла PDF.

Я пробовал добавлять exit до конца моего сценария, однако, что не закрывает терминал. Я пытался найти в Интернете ответ на свой вопрос, но не смог найти подходящий, я был бы очень признателен, если бы вы, ребята, могли помочь.

Мне нужен ответ, который убивает только терминал, с которого я запускаю команду, не все терминалы это было бы возможно? Предыдущий ответ, который я принял, убивает все открытые окна терминала. Я не осознавал, что это имело место до сегодняшнего дня.

8 ответов

Решение

Если вы открываете только один файл, вам на самом деле не нужно использовать сценарий, потому что сценарий предназначен для простого выполнения нескольких команд подряд, в то время как здесь вам просто нужно выполнить две команды (включая exit).

Если вы хотите запустить exit после команды или после цепочки команд вы можете связать ее с тем, что у вас уже есть, используя && оператор (который при успешном выполнении предыдущей команды / цепочки команд выполнит следующую команду) или с помощью ; оператор (который как при успешном, так и при неудачном завершении предыдущей команды / цепочки команд выполнит следующую команду).

В этом случае это будет что-то вроде этого:

gnome-open <path_to_pdf_file> && exit

* = путь к файлу PDF

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.

Другие вопросы по тегам