如何创建(通过安装程序脚本)一个任务来安装我的 bash 脚本以便它在 DE 启动时运行?

如何创建(通过安装程序脚本)一个任务来安装我的 bash 脚本以便它在 DE 启动时运行?

在过去的几个小时里,我一直在阅读有关 Upstart、.xinitrc、.xsessions、rc.local、/etc/init.d/、/etc/xdg/autostart、crontab 中的 @reboot 以及其他很多东西的文章,我完全糊涂了!

这是我的 bash 脚本。它应该在桌面环境启动后启动/运行,并且应该一直运行,直到注销/关机。它应该在重新启动时再次启动。只要 DE 正在运行,它就应该运行。

#!/bin/bash
while true; do
    if [[ -s ~/.updateNotification.txt ]]; then
                read MSG < ~/.updateNotification.txt 
                kdialog --title 'The software has been updated' --msgbox "$MSG"
                cat /dev/null > ~/.updateNotification.txt
    fi
    sleep 3600
done
exit 0

我对使用 Upstart 一无所知,但我知道 Upstart 是处理这个问题的一种方法。我会考虑其他方法但我读到的大多数内容对我来说太复杂了。此外,我不知道哪种方法能满足我的要求(我将在下面详细说明)。

我的问题分为两个步骤:

  1. 如何自动启动上面的脚本,如上所述。

  2. 如何通过 bash 脚本(即我的“安装程序”)“安装”该 Upstart 任务。

我假设(或希望)一旦我理解了步骤 1,步骤 2 就变得非常简单。

我必须支持所有版本的 Ubuntu 桌面。因此,上面的 kdialog 调用将被替换。我正在考虑简易BashGUI为此。(或者我可以在 gnome DE 上使用 zenity。)

我的要求是:

  1. 设置过程(安装)必须通过 bash 脚本完成。我无法使用 Ubuntu 文档中描述的 GUI 方法将程序添加到会话启动例如。我必须能够使用 bash 编写脚本/自动化安装过程。目前,这很简单,只需让 bash 安装程序脚本将上述脚本复制到/home/$USER/.kde/Autostart/

  2. 安装过程必须适用于 Ubuntu 衍生产品,包括 Unity、KDE ​​和 gnome 桌面。相同的安装脚本(安装程序)应在 Linux Mint、Kubuntu、Xbuntu(基本上是任何 Ubuntu 版本和 Linux Mint 等主要衍生产品)上运行。例如,我们不能继续放入脚本文件,/home/$USER/.kde/Autostart/因为它只存在于 KDE 上。

  3. 上述脚本应该适用于我们使用的每种有限口味。因此我们有兴趣使用简易BashGUI而不是 kdialog 或 zenity。见下文。

  4. 安装的监控脚本应该只启动桌面已启动,因为如果发现更新,它将向用户显示 GUI 消息。

    1. 当然,监控脚本(上文)应该无需 root 权限即可运行。但安装程序(bash 脚本)可以以 root 权限运行。
  5. 我不是真正的开发人员或系统管理员。这对我来说是一份兼职志愿者的工作,所以它需要简单易行。我可以编写 bash 脚本,也可以编程,但我对 Upstart 或 systemd 一无所知。而且,不幸的是,我的工作没有给我时间成为 init 系统或与开发和系统管理员相关的任何其他方面的专家。所以我必须坚持简单的解决方案。

该脚本的 easybashgui 版本可能如下所示:

#!/bin/bash
source easybashgui
while true; do
    if [[ -s ~/.updateNotification.txt ]]; then
                read MSG < ~/.updateNotification.txt 
                message "$MSG"
                cat /dev/null > ~/.updateNotification.txt
    fi
    sleep 3600
done
exit 0

答案1

启动器

/etc/xdg/autostart 中的任务由桌面环境使用当前用户的凭据启动,并且他们可以访问 GUI,所以我认为这是最好的选择。

文件 /etc/xdg/autostart/updateNotification.desktop:

[Desktop Entry]
Name=My Update Notification
Exec=updateNotification.sh
Terminal=false
Type=Application
NoDisplay=true

监控脚本

监控脚本必须放置在所有人都可访问的位置。我建议使用 /usr/local/bin,因为弄乱该目录中的文件不会影响操作系统。我对你的脚本做了一些修改。

文件 /usr/local/bin/updateNotification.sh:

#!/bin/bash

# Exit if this script is already running.
[[ $(pgrep -c -u $USER -f "^/bin/bash ${0}$") -gt 1 ]] && exit 0

NotifFile=~/.updateNotification.txt

source easybashgui

# Wait some time before starting monitoring the file, so the user doesn't get a popup right after logging in.
sleep 120

while true; do
    if [[ -s $NotifFile ]]; then
        read MSG < $NotifFile
        # Only empty the file if the message is successfully displayed.
        message "$MSG" && echo -n > $NotifFile
    fi
    sleep 3600
done

exit 0

当然,你必须下载easybashgui,解压并安装。

tar xzf easybashgui-8.0.1.tar.gz
cd easybashgui-8.0.1/
sudo make install

安装程序

我非常喜欢使用 bash 自解压文件,因为整个安装过程可以嵌入到一个文件中。我们所要做的就是将预先构建的 bash 标头与 tar 文件连接起来。

在创建档案之前,请确保所有文件都在应在的位置并具有正确的权限,在本例中:

sudo chown root:root /etc/xdg/autostart/updateNotification.desktop
sudo chown root:root /usr/local/bin/updateNotification.sh
sudo chmod 644 /etc/xdg/autostart/updateNotification.desktop
sudo chmod 755 /usr/local/bin/updateNotification.sh

我们还可以在安装程序中包含 easybashgui。将 easybashgui 存档解压到 /tmp:

tar zxf easybashgui-8.0.1.tar.gz -C /tmp

以及tar所有必需的文件:

sudo tar zcf MyArchive.tar.gz /etc/xdg/autostart/updateNotification.desktop /usr/local/bin/updateNotification.sh /tmp/easybashgui-8.0.1/

创建将解压存档并安装 easybashgui 的 bash 标头。文件 header.sfx:

#!/bin/bash
DATA=`awk '/^__BEGIN_DATA__/ { print NR + 1; exit 0; }' $0`
tail -n+$DATA $0 | tar zx -C /

# Additional installation steps
cd /tmp/easybashgui-8.0.1/
make install

exit 0

# The following line must be the last one. Don't place any character after it.
__BEGIN_DATA__

最后,合并标题和档案:

cat header.sfx MyArchive.tar.gz > MyInstaller.sh

现在您可以将该安装程序复制到另一台机器,授予其执行权限并运行sudo ./MyInstaller.sh


就是这样。希望对您有帮助。

答案2

我似乎对 Eric Carvalho 提供的出色答案遇到了一个小问题。

我创建了一个 .tar.bz 文件并测试是否可以正确提取它:

tar xzf MyArchive.tar.bz -C /home/$USERN/Downloads/

我创建了 bash header.sfx:

#!/bin/bash

USERN=`whoami`
if [ $(id -u) = "0" ] ; then
       USERN=$SUDO_USER
fi

DATA=`awk '/^__BEGIN_DATA__/ { print NR + 1; exit 0; }' $0`
tail -n+$DATA $0 | tar xz -C /home/$USERN/Downloads/
if [ $? -ne 0 ] ; then 
    exit 1
echo
# Additional installation steps follow

#bash commands here
#the last command calls my main installer script:
bash ./another_bash_script.sh

exit 0 #this is line 125
# The following line must be the last one. Don't place any character (including newline characters) after it.
__BEGIN_DATA__

我创建了自解压 shell 文件/安装程序:

cat header.sfx MyArchive.tar.bz > MyInstaller.sh

我设置了权限(a+x)。运行安装程序的结果是:

tester@mint15_VirtualBox ~/Downloads $ sudo ./MyInstaller.sh 
./ExampleInstaller.2013.07.01.sh: line 132: syntax error near unexpected token `('
./ExampleInstaller.2013.07.01.sh: line 132: `.����D������V G��c�� ��������Ӭ��ӡ|@��|M�.�/�~��w�O��*��B���l�}Ω�O�.��'

从解压文件夹内部来看,文件 MyArchive.tar.bz 似乎已正确解压。

这类错误你是否注意到了?

我的第一个猜测是它exit 0被忽略了,但我不确定为什么会出现这种情况...我注意到它exit 0在第 125 行,而错误被报告在第 132 行,它将是连接存档文件的一部分。

我接下来尝试对 headers.sfx 进行以下更改:

第一行:

#!/bin/bash -xv

最后几行:

exit 0
echo "we should never reach here!"
# The following line must be the last one. Don't place any character (including newline characters) after it.
__BEGIN_DATA__

这次的结果如下:

tester@mint15_VirtualBox ~/Downloads $ sudo ./MyInstaller.sh 
#!/bin/bash -xv
USERN=`whoami`
whoami
++whoami
[snip]
exit 0

echo "we should never reach here!"
# The following line must be the last one. Don't place any character (including newline characters) after it.
__BEGIN_DATA__
�#�Q��P\߷&�и����Ƶ��4    и��
                                           ��������Ӭ��ӡ|@��|M�.�/���B���l�}Ω�O�.
./ExampleInstaller.sh: line 134: syntax error near unexpected token `('
./ExampleInstaller.sh: line 134: `.����D���c��

实际输出包含更多“���”,但以上仅捕获了其中唯一可读的部分。

解决方案说明:

我犯的第一个错误是,我认为 header.sfx 文件的最后一行末尾不应该有换行符。见下文:

# The following line must be the last one. Don't place any character (including newline characters) after it.
__BEGIN_DATA__

原来行末应该有一个换行符__BEGIN_DATA__

我发现的第二个问题是启用 b​​ash 调试(例如set -x)会导致 awk/tail/tar 命令序列无法运行。

这两个更改使它在测试用例中对我有用。(实际上只有一个更改:纠正我对最后换行符的误解。)

然而,在我的实际例子中,我遇到了其他问题。事实证明,文件的文件权限里面存档确实很重要。我的存档中有一个文件的权限非常严格,这个文件导致整个自解压 bash 脚本在提取阶段失败。但是,在 GUI 文件管理器中进行手动提取或使用 tar 进行命令行提取均成功。因此,自解压 bash 脚本对存档内的文件权限等内容更敏感(我不是在谈论存档本身的权限)。

此外,任何“尾随垃圾”都会导致自解压 bash 脚本失败。示例:

gzip: stdin: decompression OK, trailing garbage ignored

我从一个存档中收到此消息,自解压 bash 脚本在解压后无法执行任何命令(尽管解压似乎没有问题,如消息所示)。类似的东西可能2> /dev/null会解决最后一个问题...

相关内容