web-dev-qa-db-ja.com

DEの起動時に実行されるようにbashスクリプトをインストールするタスクを(インストーラースクリプトを介して)作成する方法は?

過去数時間、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つのステップがあります。

  1. 上記のように、上記のスクリプトを自動的に開始する方法。

  2. Bashスクリプト(つまり、私の「インストーラー」)を介してそのUpstartタスクを「インストール」する方法。

ステップ1を理解すれば、ステップ2はほとんど些細なことであると思います(または期待します)。

Ubuntuデスクトップのすべてのフレーバーをサポートする必要があります。したがって、上記のkdialog呼び出しは置き換えられます。このために easybashgui を検討しています。 (または、GNOME DEでzenityを使用できます。)

私の要件は次のとおりです。

  1. セットアッププロセス(インストール)は、bashスクリプトを介して実行する必要があります。 Ubuntuのドキュメントに記載されているGUIメソッドを使用できません AddingProgramToSessionStartup など。 bashを使用してセットアップ(インストール)プロセスをスクリプト化/自動化できる必要があります。現在、bashインストーラースクリプトが上記のスクリプトを/home/$USER/.kde/Autostart/にコピーするのと同じくらい簡単です。

  2. セットアッププロセスは、Unity、KDE、およびgnomeデスクトップを含むUbuntu派生製品全体で共通である必要があります。同じセットアップスクリプト(インストーラー)は、Linux Mint、Kubuntu、Xbuntu(基本的にUbuntuのすべてのフレーバーとLinux Mintなどの主要な派生製品)で実行する必要があります。たとえば、スクリプトファイルを/home/$USER/.kde/Autostart/に配置し続けることはできません。これは、KDEにのみ存在するためです。

  3. 上記のスクリプトは、使用する限られたフレーバーごとに機能するはずです。したがって、kdialogまたはzenityの代わりに easybashgui を使用することに興味があります。下記参照。

  4. インストールされた監視スクリプトは、GUIメッセージを表示するため、デスクトップを起動した後のみ開始する必要があります更新が見つかった場合、ユーザーに。

    1. もちろん、監視スクリプト(上記)はルート権限なしで実行する必要があります。ただし、インストーラー(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
3
MountainX

ランチャー

/ 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をお勧めします。そのディレクトリ内のファイルをいじってもOSには影響しないからです。スクリプトを少し変更しました。

ファイル/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

もちろん、 download easybashguiを展開し、展開してインストールする必要があります。

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

インストーラー

インストールプロセス全体を1つのファイルに埋め込むことができるため、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

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__

自己解凍シェルファイル/インストーラーを作成しました。

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__

2つ目の問題は、bashデバッグを有効にすることです(例:set -x)コマンドのawk/tail/tarシーケンスが機能しないようにします。

これら2つの変更により、テストケースで機能しました。 (そして、それは本当に1つの変更でした:最終的な改行文字についての私の誤解を修正します。)

しかし、実際の例では、追加の問題が発生しました。ファイルのファイル許可insideアーカイブは重要です。アーカイブ内に非常に制限されたアクセス許可を持つファイルが1つあり、このファイルにより、抽出フェーズで自己解凍型bashスクリプト全体が失敗しました。ただし、GUIファイルマネージャでの手動抽出またはtarを使用したコマンドライン抽出は両方とも成功しました。そのため、自己解凍型のbashスクリプトは、アーカイブ内のファイルのアクセス許可などの影響を受けやすくなっています(アーカイブ自体のアクセス許可については説明していません)。

また、「トレーリングガベージ」があると、自己解凍型bashスクリプトが失敗します。例:

gzip: stdin: decompression OK, trailing garbage ignored

1つのアーカイブからこのメッセージがあり、自己抽出bashスクリプトは、抽出後のコマンドの実行に失敗しました(メッセージが示すように、抽出は正常に見えたとしても)。 2> /dev/nullはこの最後の問題に対処します...

0
MountainX