【问题标题】:Linux shell script not executing completely as desktop shortcutLinux shell 脚本没有完全作为桌面快捷方式执行
【发布时间】:2025-12-09 01:50:01
【问题描述】:

我希望创建一个 shell 脚本,以便在我开始工作日时打开一组应用程序。我发现了几个帖子like this,这似乎是我要找的。问题是,当我双击它时脚本不起作用。

如果我从终端启动脚本,它会完全执行,但我不想总是从终端调用它,我想双击一个快捷方式。如果我在末尾添加“睡眠 1”,它大部分时间都可以工作,但这里的问题是 1 秒并不总是足够的时间来执行所有操作。此外,它只是感觉非常不精确。当然,我可以说“sleep 10”并完成它,但作为开发人员,这感觉像是一个 hack 解决方案。

这是我当前的脚本,我打算随着时间的推移将我的应用程序添加到此列表中,但现在就足够了:

#!/bin/bash
skype &
/opt/google/chrome/google-chrome &
geany &
mysql-workbench &

所以问题是:我怎样才能确保一切都开始了,但又不会让临时终端窗口的打开时间超过它需要的时间?

如果重要的话,为了创建这个脚本,我只需将一个 .sh 文件保存到桌面并在文件属性中选中“允许将文件作为程序执行”。

【问题讨论】:

  • 当它不能完全工作时,您是否意味着某些应用程序无法启动?一样的吗?最后一个?随机的?您是否也考虑过在桌面环境中设置自动启动应用程序?
  • 澄清一下,没有任何应用程序启动。我只看到一个闪烁的终端窗口。奇怪的是,它可以通过终端正常执行(在同一用户下运行,而不是以 root 身份运行),或者如果我在脚本末尾添加“睡眠”。我不想自动启动任何应用程序,因为这是一台个人电脑,只是偶尔用于工作目的。

标签: linux shell desktop-shortcut


【解决方案1】:

尝试在每个命令前加上nohup

#!/bin/bash nohup Skype & nohup /opt/google/chrome/google-chrome & nohup geany & nohup mysql-工作台 &

更好的是,使用循环:

#!/bin/bash 应用程序="skype /opt/google/chrome/google-chrome geany mysql-workbench" $apps 中的应用程序;做 nohup $app & 完毕

如果出现任何错误,请查看nohup.out 的消息。

【讨论】:

  • 这两种方法都会导致终端窗口短暂闪烁,实际上并没有执行任何操作。就像我在上面发布的示例一样,从终端调用时出于某种原因,这在双击快捷方式时不起作用。双击执行时不会生成'nohup.out'文件。
  • 这种循环方法是合理的,但做得很糟糕。 apps 应该 not 是一个字符串,它应该是一个数组 apps=(app1 app2 "app 3" ...) 并且循环应该是 for app in "${apps[@]}"; do 以允许具有空格和 shell 元字符的应用程序。
【解决方案2】:

我认为这个问题的原因是太早关闭了 I/O 文件(很可能是 ttys)。您可以尝试重定向所有 I/O(stdin、stdout、stderr),例如:

skype < /dev/null > /dev/null 2 > /dev/null &

这样的事情也应该有效:

#!/bin/sh
{
  skype &
  /opt/google/chrome/google-chrome &
  geany &
  mysql-workbench &
} < /dev/null > /dev/null 2 > /dev/null &

编辑:

我可以在 Ubuntu 12.04 上重现它。关闭时似乎终端程序会杀死pgroup 中的所有进程。尝试过:

/usr/bin/gnome-terminal -x /bin/sh -c ./test.sh
xterm -e ./test.sh`

结果是一样的——没有sleep 程序不会出现。似乎是终端,当脚本完成时将 SIGHUP 发送到 shell 脚本的 pgroup。您可以通过strace -f 运行上述任何程序来查看它。在列表末尾应该有 kill(PID,SIGHUP) 带有非常大的 PID 号作为参数 - 实际上它是负数,所以 SIGHUP 被发送到 pgroup 中的所有进程。

我会假设许多 X11 忽略 SIGHUP。问题是 SIGHUP 在更改默认行为之前已发送/接收。对于sleep,您正在给一些时间来更改 SIGHUP 处理。

我试过disown(bash 内置),但没有帮助(SIGHUP 到 pgroup 是从终端发送的,而不是 shell)。

编辑:

一种可能的解决方案是制作script.desktop 文件(您可以使用一些现有的.desktop 文件作为模板,在Ubuntu 上这些文件位于/usr/share/applications)并从该文件启动您的脚本。似乎即使是不忽略 SIGHUP (xclock) 的 X11 程序也通常以这种方式启动。

【讨论】:

  • 什么都没有发生:-/如果发布的解决方案都不起作用,我认为我的环境一定有问题。除了安装一些应用程序之外,我正在运行 Linux Mint 16.1,只进行了一些修改。
  • @CauselessEffect,对,可以重现该问题。到目前为止,我发现的唯一解决方法是使用 .desktop 文件(答案已更新)。
  • 感谢您为帮助我解决这个问题付出了这么多努力!我查看了几个示例 .desktop 文件,我猜我关心的行是“Exec=/”。我不熟悉这些文件的使用位置,我该如何测试呢?
  • @CauselessEffect,不客气,我在这里也学到了一些东西。是的,只需更改 Exec= 以指向您的脚本。然后像您对原始脚本所做的那样双击此文件。 linuxcritic.wordpress.com/2010/04/07/anatomy-of-a-desktop-file 可以作为快速介绍。
【解决方案3】:
  1. 首先,您似乎有一个 TRAILING & 符号 (&amp;) ...这可能会导致一些问题。

  2. 其次,您可以执行以下操作以确保仅在成功时退出 shell(即执行):

    #!/bin/bash
    
    skype & /opt/google/chrome/google-chrome & geany & mysql-workbench
    
    if [ $? -eq 0 ]
    then
      echo "Successfully completed operation (launched files, etc...)"
    
      #use if you don't want to see anything/be notified if successful
      ## 'exit 0' will exit TERMINAL, therefore the SCRIPT AS WELL
      ## indicating to the shell that there was NO ERROR (success)
      #exit 1  
      exit 0    
    
      ## 'return 0' will allow the "successful" message to be written 
      ## to the command-line and then keep the terminal open, if you
      ## want confirmation of success. The SCRIPT then exits and 
      ## control returns to terminal, but it will not be forced close.
      return 0
    
    else
      echo "Operation failed!" >&2
      ## 'exit 1' will exit the TERMINAL, and therefore the SCRIPT AS 
      ## WELL, indicating an ERROR to the shell 
      #exit 1  
    
      ## 'return 1' will exit the SCRIPT only (but not the terminal) and 
      ## will indicate an ERROR to the shell
      return 1
    
    fi
    

【讨论】:

  • 这似乎可以正常工作,但是有几次终端窗口没有关闭并且仍然连接到进程。我的意思是如果我关闭终端窗口,它打开的所有应用程序也会立即关闭!
【解决方案4】:

** 更新 **

(请注意,我在下面的答案末尾添加了一个 & 符号 &amp;

你可以做一个单行。以下将依次运行所有命令,一次一个,每个命令仅在前一个结束时/当前一个结束时运行。如果并且当&amp; 之间的任何单个命令失败时,命令行语句将终止。

(skype && /opt/google/chrome/google-chrome && geany && mysql-workbench) && echo "Success!" || echo "fail" &

【讨论】:

  • 不幸的是,这个命令只打开了 Skype,当我关闭悬挂的终端窗口时,它也杀死了 Skype!
最近更新 更多