运行bash脚本后退出终端


18

我正在尝试编写一个bash脚本来使用该gnome-open命令打开某些文件(主要是pdf文件)。我也希望终端在打开pdf文件后退出。

我尝试将exit脚本添加到脚本末尾,但这不会关闭终端。我确实尝试过在网上搜索问题的答案,但找不到合适的答案,如果你们能提供帮助,我将非常感谢。

我需要一个仅杀死运行该命令的终端的答案,不是所有终端都可以吗?我接受的先前答案会杀死所有打开的终端窗口。直到今天我才意识到情况确实如此。


您首先是在终端中运行脚本吗?严格从命令行开始,没有理由打开终端这样做。
Jacob Vlijm

是的,我从终端运行脚本。我没有意识到终端机和命令行之间的区别
Rumesh 2015年

我在脚本中将替换为gnome-openxdg-open但没有任何变化。航站楼仍保持打开状态
Rumesh 2015年

@Tim Wow,它有效=)+1
AB

@Tim但是我的解决方案也不错。;)
2015年

Answers:


12

如果您只打开一个文件,则实际上不需要使用脚本,因为脚本是连续运行多个命令的一种简便方法,而在这里,您只需要运行两个命令(包括exit) 。

如果要exit在命令后执行,也可以在命令链后运行,则可以通过使用&&运算符(在上一个命令成功执行时/命令链执行下一个命令时)将其链接到已经存在的内容上。;运算符(上一个命令/命令链的成功与否都会执行下一个命令)。

在这种情况下,将是这样的:

gnome-open <path_to_pdf_file> && exit

* <path_to_pfd_file> = pdf文件的路径

exit放在脚本末尾的脚本不起作用,因为它仅退出bash运行脚本的实例,该bash实例是Terminal内部bash实例之外的另一个实例。

如果仍然要使用脚本,最直接的方法就是像下面这样调用脚本:

<path_to_script> && exit

或者,如果脚本位于终端的当前工作目录中,则如下所示:

./<script> && exit

如果您真的不想/不能这样做,第二种最直接的方法是在脚本的末尾添加以下行:

kill -9 $PPID

这会将SIGKILL信号发送到脚本的父进程(bash链接到Terminal 的实例)。如果只有一个bash实例链接到终端,则该实例被杀死将导致终端关闭自身。如果有多个bash实例链接到终端,则被杀死不会导致终端自行关闭。


2
SIGTERM信号被发送到进程以请求终止。与SIGKILL信号不同,该信号可以被过程捕获,解释或忽略。这允许进程执行良好的终止,释放资源并在适当的情况下保存状态。SIGINT与SIGTERM几乎相同。
AB

@AB是的,SIGTERM这还不够。
kos 2015年

谢谢回复。我想我会只使用您在回答中给出的单个命令
Rumesh

kill $ PPID的作用与退出相同-无。然后kill -9 $ PPID与父级一起关闭所有子级窗口。
SDsolar '17

5

该脚本终止终端,并因此终止外壳和自身。

它无情地杀死了所有进程。如果您在终端中打开了多个选项卡,则这些选项卡也会关闭。

问题是,如果打开了多个终端,而这些终端是的子进程gnome-terminal-server,则所有终端将被杀死。

在这种情况下,脚本应在独立的终端中启动,例如 xterm

<your_command> & disown

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

    PPID是父进程ID,在本例中为shell(e.g. /bin/bash

  • PPPID

    PPPID是PPID的父进程ID,在这种情况下为终端窗口

  • <your_command> & disown

    在bash Shell中,disown Builtin内置命令用于从作业表中删除作业,或标记作业,以便如果父外壳收到SIGHUP信号(例如,如果用户注销),则不会将SIGHUP信号发送给它们。

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

    获取文件第四列的值/proc/$PPID/stat(例如,/proc/1/stat它返回0)


我认为命令$$ get是终端的pid ...那可以替代吗?您还能解释一下如何取消所有权吗?
2015年

这个脚本是如何做到的?我仍然对Shell脚本还不熟悉,因此我无法真正理解这些命令。能否请你解释它是如何关闭终端
Rumesh

1
@Tim否,它将在终端中返回外壳:ps xa | grep $$=> 4381 pts/0 Ss 0:01 /usr/bin/zsh
AB

1
@RumeshSudhaharan它杀死启动脚本的整个终端窗口,但不会杀死其他终端窗口。
AB

3
@AB您之前说过,这只会杀死当前的终端窗口,而不会杀死其他任何窗口。今天,我在打开两个终端窗口的情况下使用了此脚本,运行脚本后,两个窗口均被杀死。
Rumesh 2015年

4

您可以使用。exec ./your-script

当其中运行的初始进程(通常是外壳程序)退出时,像GNOME Terminal这样的终端模拟器就会退出。

如果您已经在终端中,并且退出该终端之前唯一要做的就是运行特定的脚本(或程序),那么这意味着您不再需要真正在其中运行的shell。因此,您可以使用Shell的exec内置函数使Shell 命令创建的进程替换自身

  • 就您的脚本而言,这是另一个Shell进程-就像运行不带的脚本时如何创建第二个 Shell进程一样exec

语法例如是。exec commandexec ./your-script

exec: 一个例子

例如,假设我有一个名为的shell脚本count,标记为可执行文件,并且位于当前目录中。它包含了:

#!/usr/bin/env bash
for i in {5..1}; do echo $i; sleep 1; done

并且,在终端中,我运行:

exec ./count

此打印的标记5432,和1,每秒一个,然后该终端窗口关闭。

如果您从终端上运行的第一个进程之外的其他东西运行它(例如,如果您bash首先运行以启动另一个Shell实例),那么这会将您带回到创建进程的Shell ,而不是退出终端。(此警告同样适用于exit基于方法的方法。)

您可以使用。./your-script; exit

如果您不想告诉您的shell用新进程替换自己(通过exec),则可以告诉它继续存在,但是在新进程完成后立即退出。

为此,请运行命令,然后将exit命令分隔开,;以便可以在一行上给出它们。

语法command; exit例如是。./your-script; exit

command; exitcommand && exit

您可能会注意到这看起来类似的建议方法科斯的heemayl的答案。区别在于:./your-script && exit

  • &&仅当第一个命令通过返回退出代码零来成功执行第二个命令时,才运行第二个命令。
  • ; 不管第一个命令是否报告成功,都运行第二个命令。

您想要哪一个取决于具体情况。如果命令失败,您是否要使调用外壳程序(和托管终端)保持正常运行?如果是这样,请使用&&; 如果没有,请使用;

还有一个command || exit,只有在command报告失败时才退出调用Shell 。


2

您可以获取脚本而不是运行它,例如

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

1

我个人将执行命令以打开子外壳中的pdf或其他文件,放置一些延迟以使文件打开,然后退出。基本上,这是我测试过的(nohup gnome-open *.pdf &); sleep 2; exit

对此的变化是 nohup gnome-open *.pdf && sleep 2 && exit


就我而言,由于nohup忽略了挂断信号,因此nohup xdg-open some_program对我有用,并且exit是不必要的。nohup将消息重定向到nohup.out文件:nohup: ignoring input and appending output to nohup.out
nick indiessance

0

最简单的解决方案是:

xdg-open file.pdf && exit

与其他nohup不需要使该命令忽略的类似命令不同SIGHUP,原因是xdg-open将退出生成子进程,这是打开pdf文件的首选应用程序。由于不再nohup需要从终端启动的实际进程被杀死,因此不再需要。

&&表示如果前一个命令成功执行,则将运行下一个命令,即返回退出代码0$?=0),exit并仅关闭终端。


我认为他说退出无法正常运作
2015年

@Tim:也许OP没有用正确的方式,从问题的很不清楚我怎么他/她把exit在最后并没有工作..
heemayl

1
@Tim因为OP放在exit脚本内,所以没有用,因为它具有退出bash正在执行脚本的实例而不是父bash实例(链接到Terminal的实例)的作用,这将导致Terminal关闭
kos

1
无论如何xdg-open,该脚本已经在后台运行并且与终端没有链接,因此您不需要nohup在这里,而且据我了解,OP xdg-open在一个脚本中多次运行可以批量打开多个文件,xdg-open就像在脚本中那样使用会导致该脚本第一次xdg-open发生时退出
kos 2015年

@kos:没有,我没有运行xdg-open在backgr,即使我有nohup是出于不同的原因和必须从始发终端将被杀死时,你会杀死为父终端there..any后台进程.. nohup,以防止有it..as我不需要交互再次使用的终端,没有必要把过程bg..on这也可以通过运行的每个防止你的第二点xdg-open && exit在子shell ..
heemayl

0

要明确回答标题问题,

“运行bash脚本后退出终端”

在终端中仅运行脚本

无需查看脚本的详细信息,就可以在带有选项-e--command)的终端中直接运行脚本,而无需启动外壳程序-而是使用它代替外壳程序:

gnome-terminal -e ./script.sh

要为脚本提供参数时,请使用选项-x--execute)。这样,仅将命令行的其余部分用作命令和参数。

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

如果您的脚本退出,则没有交互式外壳程序可以通过等待用户输入来容纳任何内容。

例子

终端将在其中运行的命令退出后才退出-像这样,在sleep运行4秒后关闭,没有shell:

gnome-terminal -x sleep 4

当然,您可以使用Shell脚本,因为您的脚本仍然使用其他Shell实例。

另外,您可以使用显式脚本运行外壳程序-它不会是交互式的:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.