キックスタート中にシェルスクリプトをバックグラウンドにどのように配置できますか?

キックスタート中にシェルスクリプトをバックグラウンドにどのように配置できますか?

ヘルスサーバーにPOST要求を行い、重要なことについての進捗状況を報告するRed Hat Kickstartプロセスがあります。

%pre途中で大丈夫ですが、%post実際のビルドが発生すると情報ブラックホールになります。

進行状況のおおよそのアイデアを提供するために、インストールされているパッケージの数を報告する簡単なシェルフラグメントを作成しました。私は以下を入れました%pre

%pre

## various other stuff here, all works fine ##

cat > /tmp/rpm_watcher.sh << EOF_RPM
PREV=-1
while true
do
    COUNT="\$(rpm -qa | wc -l)"
    if [ \${COUNT} -ne \${PREV} ] ; then
        /bin/wget --post-data " ${Hostname} : Package count \${COUNT}" ${builddest}/log
        PREV=\${COUNT}
    fi
    sleep 15
done
EOF_RPM
/bin/sh /tmp/rpm_watcher.sh &
disown -a
%end

ただし、上記からバックグラウンドジョブで起動すると、%preスクリプトが完了するのを待たずに%pre完了しません(生成されたスクリプトを終了すると完了%preし、ビルドが正しく開始されます)。

プリインストールされた環境では使用できないため使用できません。nohupと を使用する場合も同様です。at nowscreen

を試してみましたが、disown -a利用可能です。プロセスは正常に拒否されたようですが(PID 1に属しています)、まだスクリプトが完了するまで停止します。

誰でも私に代替案を提供できますか?

答え1

あなたは解決策に非常に近いです。 Anaconda(インストールプログラム)はPythonで書かれているので、コードを詳しく見ました。

最終的に次のスクリプトを実行します。

    rc = iutil.execWithRedirect(self.interp, ["/tmp/%s" % os.path.basename(path)],
                                stdin = messages, stdout = messages, stderr = messages,
                                root = scriptRoot)

詳しくは、「iutil.py」で定義されているiutil.execWithRedirectを見つけることができます。この関数は最終的に subprocess.Popen(Python 組み込み) を使用してコマンドを実行します。 %preスクリプトからSTDOUTとSTDERRの内容を取得するのも非常に困難です。

コードは次のとおりです。

    #prepare tee proceses
    proc_std = tee(pstdout, stdout, program_log.info, command)
    proc_err = tee(perrout, stderr, program_log.error, command)

    #start monitoring the outputs
    proc_std.start()
    proc_err.start()

    proc = subprocess.Popen([command] + argv, stdin=stdin,
                            stdout=pstdin,
                            stderr=perrin,
                            preexec_fn=chroot, cwd=root,
                            env=env)

    proc.wait()
    ret = proc.returncode

    #close the input ends of pipes so we get EOF in the tee processes
    os.close(pstdin)
    os.close(perrin)

    #wait for the output to be written and destroy them
    proc_std.join()
    del proc_std

    proc_err.join()
    del proc_err

したがって、現在持っているものを使用すると、バックグラウンドに分岐してproc.wait()とos.close呼び出しをバイパスできます。

proc_std と proc_err は繰り返し呼び出されるスレッドです。読書船STDOUTとSTDERRから。 EOFに会うまで読み続けます。スクリプトは%preスクリプトからSTDOUTおよびSTDERRソケットを継承するため、EOFは発生しません。その後、Anacondaは中断され、STDOUTを読み取るスレッドが終了するのを待ちますが( "proc_std.join()"行で)これは決して起こりません。

これは非常に混乱している問題ですが、最終的に非常に簡単な解決策です。変える:

/bin/sh /tmp/rpm_watcher.sh &

使用

/bin/sh /tmp/rpm_watcher.sh > /dev/null 2>&1 < /dev/null &

これにより、スクリプトはSTDOUTとSTDERRを継承しないため、Anacondaが中断されずにインストールを続行できます。

答え2

次のようにスクリプトを背景にする代わりに、スクリプトのwhileループを背景に設定する場合:

while true
do
    COUNT="\$(rpm -qa | wc -l)"
    if [ \${COUNT} -ne \${PREV} ] ; then
        /bin/wget --post-data " ${Hostname} : Package count \${COUNT}" ${builddest}/log
        PREV=\${COUNT}
    fi
    sleep 15
done &

doneループ行の末尾に「&」記号を追加しましたwhile

引用する

答え3

おそらくAnacondaの実装は、提案された解決策を破るために進化したでしょう。私はこのプロセスを決して否定できない。

これでAnaconda環境で利用できるようになりますsystemd。これは私にとって効果的でした(適応問題)。

cat > /etc/systemd/system/rpm-watcher.service << EOF
[Service]
Type=simple
ExecStart=/bin/sh /tmp/rpm_watcher.sh
EOF

systemctl daemon-reload
systemctl start rpm-watcher

答え4

まあ、時々at now""で始まるのが私には大丈夫です。

すぐに返され、開始されたプロセスはバックグラウンドで実行されます。

atd当然走らなければなりません:)

例えば

/bin/echo "/custom/scripte/test.sh" | /usr/bin/at now

関連情報