it-roy-ru.com

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

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

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

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

16
Rumesh

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

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

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

gnome-open <path_to_pdf_file> && exit

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

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

Если вы хотите использовать скрипт в любом случае, самый простой способ - просто вызвать скрипт так:

<path_to_script> && exit

Или, если скрипт находится в текущем рабочем каталоге Терминала, вот так:

./<script> && exit

Если вы действительно не хотите/не можете этого сделать, второй самый простой способ - добавить эту строку в конец вашего скрипта:

kill -9 $PPID

Это отправит сигнал SIGKILL в родительский процесс сценария (экземпляр bash, связанный с Терминалом). Если с Терминалом связан только один экземпляр bash, то уничтожение приведет к тому, что Терминал закроется сам. Если с Терминалом связано несколько экземпляров bash, то уничтожение не приведет к закрытию Терминала.

12
kos

Этот скрипт завершает работу терминала и, следовательно, Shell и самого себя.

Это беспощадно убивает все процессы. Если в терминале открыто несколько вкладок, они также закрываются.

Проблема в том, что если открыто несколько терминалов, а это дочерние процессы gnome-terminal-server, все терминалы будут уничтожены.

В этом случае скрипт должен быть запущен в независимом терминале, например, xterm

<your_command> & disown

PPPID=$(awk '{print $4}' "/proc/$PPID/stat")
kill $PPPID
  • PPID

    PPID является идентификатором родительского процесса, в данном случае Shell (e.g. /bin/bash)

  • PPPID

    PPPID - это идентификатор родительского процесса PPID, в данном случае это окно терминала.

  • <your_command> & disown

    В командной консоли bash встроенная команда disown используется для удаления заданий из таблицы заданий или для пометки заданий, чтобы им не отправлялся сигнал SIGHUP, если родительский Shell получает его (например, если пользователь выходит из системы).

  • awk '{print $4}' "/proc/$PPID/stat"

    Получает значение четвертого столбца файла /proc/$PPID/stat (например, для /proc/1/stat возвращает 0)

4
A.B.

Вы можете использовать exec ./your-script.

Эмулятор терминала, такой как GNOME Terminal, закрывается, когда завершается начальный процесс, выполняющийся внутри него - обычно это Shell.

Если вы уже находитесь в терминале, и единственное, что вы хотите сделать перед выходом из этого терминала, - это запустить определенный скрипт (или программу), то это означает, что вам больше не нужна оболочка, которая в нем работает. Таким образом, вы можете использовать встроенную в оболочку exec, чтобы оболочка заменила себя на процесс, созданный вашей командой.

  • В случае с вашим сценарием это еще один процесс Shell - так же, как создается второй процесс Shell при запуске сценария без 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, чтобы запустить другой экземпляр Shell - тогда это вернет вас к созданной оболочке обрабатывать, а не выходить из терминала. (Это предупреждение в равной степени относится к методам на основе exit.)

Вы можете использовать ./your-script; exit.

Если вы не хотите, чтобы ваша Shell заменила себя новым процессом (через exec), вы можете попросить его остаться, но выйти сразу после завершения нового процесса.

Для этого запустите вашу команду и команду exit, разделенные ;, чтобы они могли быть указаны в одной строке.

Синтаксис: command; exit, например, ./your-script; exit.

command; exit против command && exit

Вы можете заметить, что это похоже на метод ./your-script&& exit, предложенный в kos's и heemayl's ответах. Разница в том, что:

  • && выполняет вторую команду только в том случае, если первая команда сообщила, что она выполнена , возвращая код завершения, равный нулю.
  • ; выполняет вторую команду независимо от того, сообщила ли первая команда об успешном выполнении.

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

Существует также command || exit, который выходит из вызывающей оболочки, только если command сообщил о сбое .

3
Eliah Kagan

Вы можете использовать свой сценарий вместо его запуска, например

$ cat run.sh
exit;
$ ./run.sh #will not close
$ . ./run.sh # will close
1
RiaD

Чтобы явно ответить на заглавный вопрос,

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

Запускай только свой скрипт в терминале

Не смотря на детали того, что делает скрипт, скрипт может быть запущен непосредственно внутри терминала с параметром -e (--command), без запуска Shell - он используется вместо Shell тогда:

gnome-terminal -e ./script.sh

Используйте параметр -x (--execute), если вы хотите предоставить аргументы скрипту. При этом только вся остальная часть командной строки принимается в качестве команды и аргументов.

gnome-terminal -x ./script.sh foo bar

Если ваш скрипт завершается, не существует интерактивной оболочки, которая могла бы задержать что-либо, ожидая ввода данных пользователем.

Примеры

Теминал просто завершится после того, как выйдет запущенная в нем команда - вот так, закрываясь после того, как sleep пробежит 4 секунды без Shell:

gnome-terminal -x sleep 4

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

Также вы можете запустить Shell с явным сценарием - он не будет интерактивным:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
0
Volker Siegel

Самое простое решение было бы:

xdg-open file.pdf && exit

В отличие от других подобных команд, Nohup не требуется, чтобы команда игнорировала SIGHUP, причина в том, что xdg-open завершит работу, порождая дочерний процесс, который является предпочтительным приложением для открытия файла PDF. Поскольку фактический процесс, запущенный из терминала, больше не подлежит уничтожению, Nohup не требуется.

&& указывает, что следующая команда будет выполнена, если предыдущая команда будет успешной, т.е. вернет код выхода 0 ($?=0) и exit просто закроет терминал.

0
heemayl

Лично я выполнил бы команду, чтобы открыть pdf или другие файлы в подоболочке, отложил задержку, чтобы открыть файлы, и затем завершил работу. В основном вот что я проверил (Nohup gnome-open *.pdf &); sleep 2; exit

Вариация на это будет Nohup gnome-open *.pdf && sleep 2 && exit

0
Sergiy Kolodyazhnyy