web-dev-qa-db-ja.com

Golangプロセスをバックグラウンドで実行するにはどうすればよいですか?

この質問は厳密にはプログラミング関連ではありませんが、プログラマーにとっては確かに重要です。

単純なSMTPサーバーを作成しました。コンソールから実行すると、コマンドラインをブロックしていることを除いてすべて問題ありません。

私はそれを介して実行できることを知っています

Nohup ... &

またはscreen/tmuxなどを介して

しかし、問題は、バックグラウンドで実行されるプログラムをどのように実装すればよいかということです。システム管理者がプログラムをセットアップしてプロセスを管理するのは楽しいことでしょうか。

golang-nuts で、私よりはるかに経験のある人の中には、フォークなどを使用せず、monitなどの形式の「ラッパー」を使用している人もいます。

ターゲットプラットフォームはDebianベースであり、ボックス上の他のすべてのものはinit.dベースです。

そのトピックまたはよく書かれたサンプルプロジェクトのソースのための良いリソースはありますか?

15
astropanic

Nickが述べたように Supervisord は、私の経験でもうまく機能した素晴らしいオプションです。

Nickは、フォークの問題について言及しました。フォーク自体はうまく機能します。問題はフォークではなく、特権の削除です。 Goランタイムがゴルーチンが多重化されるスレッドプールを開始する方法(GOMAXPROX> 1の場合)により、setuidシステムコール アクセス許可を削除する信頼できる方法ではありません

代わりに、非特権ユーザーとしてプログラムを実行し、 setcap ユーティリティを使用して必要な権限を付与する必要があります。

たとえば、低いポート番号(80など)へのバインドを許可するには、実行可能ファイルでsetcapを1回実行する必要があります。Sudo setcap 'cap_net_bind_service=+ep' /opt/yourGoBinary

Setcapをインストールする必要があるかもしれません:Sudo aptitude install libcap2-bin

24
voidlogic

すでに良い答えがありますが、いくつかの追加情報を追加します。

プロセスのバックグラウンド処理を行うために、Debianにsupervisordなどの追加のソフトウェアをインストールする必要はありません。

Debianには、_start-stop-daemon_スクリプトでデーモンを起動するための標準的な方法である_init.d_と呼ばれるツールが付属しています。プログラムがそれ自体でそれを行わない場合、それはまたあなたのためにプロセスをバックグラウンドに置くことができます。 _--background_オプションをご覧ください。

Initスクリプトの基礎として_/etc/init.d/skeleton_を使用しますが、do_start()関数を次のように変更します。

_start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \
    --background --exec $DAEMON --test > /dev/null \
            || return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \
    --background --exec $DAEMON -- $DAEMON_ARGS \
            || return 2
_

また、PIDファイルを作成する_--make-pidfile_オプションを追加しました。

安全な方法で別のユーザーに切り替える必要がある場合は、_--chuid_オプションもあります。

UbuntuおよびRHEL/CentOS/SL 6.Xでは、最も簡単な方法はupstartジョブ構成ファイルを作成することです。 _exec /usr/sbin/yourprogram_を_/etc/init/yourprogram.conf_構成ファイルに入れるだけです。 upstartを使用すると、プログラムをバックグラウンドで強制する必要はありません。従来のデーモンで必要な_expect fork_または_expect daemon_を追加しないでください。 upstartでは、プロセスがフォークしない方が良いです。

16
snap

私は ブログ投稿 これについてしばらく前に書いた。デーモン化のアイデアは、他にも多くの心配事が残るため、私には間違っているように思われます(たとえば、失敗するとどうなるか、プロセスの再起動をどのように管理するか、ロギング、作業ディレクトリ、コア、システムの再起動をどのように処理するか) 、など...)

結局のところ、あなたがそうしないなら、物事ははるかに簡単になります。

10
Dustin

Supervisord 私の経験では、これには非常にうまく機能します。

コマンドラインで実行するようにアプリを作成し、印刷物などを作成すると、supervisordがすべてのデーモン化、問題が発生した場合の再起動、レート制限などを処理します。

ランタイムがmain()ルーチンを実行する前にいくつかのスレッドを開始するため、従来のUNIXの方法でgoプログラムをバックグラウンドにフォークすることは難しいと思います。

5
Nick Craig-Wood

しかし、問題は、バックグラウンドで実行されるプログラムをどのように実装する必要があるかということです。システム管理者がプログラムをセットアップしてプロセスを管理するのは楽しいことでしょうか。

ここでいくつかの考え。

パッケージとリポジトリを提供する

ソフトウェアのインストールは1つのことであり、ソフトウェアの保守と実行はまったく別の話です。確かに、Zipをダウンロードして解凍し、ファイルを適切なディレクトリに配置し(通常、パッケージはファイルシステム全体に散在していることに注意してください)、デーモンを実行するシステムユーザーを作成し、それに応じたアクセス許可を設定できます。しかし、これは面倒でエラーが発生しやすく(「Bah!実行されません!修正してください!」などのチケットが大量に流入することになります)、ソフトウェアを多くのシステムにインストールする場合はほとんど実用的ではありません。

したがって、採用のハードルを下げるためのパッケージが必要です。これらのパッケージのリポジトリを提供することは、通常、ロケット科学ではなく、インストールや更新をはるかに簡単にします。 「ダウンロード->配布->インストール/更新」と次のような単一のコマンド/サーバーには違いがあります

$ awesomePm update coolApplication

少なくともRedHatおよびDebianベースのシステム用のパッケージを提供します。個人的には、CentOS(パッケージをほぼすべてのRHEL派生物と互換性があるようにする)と基本的なDebianを選びます。後者は、Ubuntu用のパッケージを提供することも簡単にする必要があります。私はDebianや派生物をもう使用していないので、それらが本当に互換性があるかどうかはあまりわかりません。最後に.debをビルドしたときに起動の問題がありました。

適切なドキュメントを提供します。何が、どこに、そしてなぜインストールされているかを文書化します。対応するドキュメントへのリンクを提供します。依存関係へのマンページ参照で十分です。このようにして、最も経験の浅い管理者でもパッケージを構成できるようにします。

最も防御的で健全なデフォルトを使用します

golangに関する特記事項:ほとんどのパッケージビルドツールは、デフォルトでパッケージに含まれているバイナリを削除します。 Goはそれをサポートしていないので、ここで注意してください。

完全である

不完全なパッケージほど迷惑なものはありません。

可能な限りsyslogを使用し、その規則に従います。このようにして、ログはシステム管理者が期待する場所に配置され、ログが自動的に古くなった場合に処理され、アプリケーションがディスクをいっぱいにするのを防ぎます。システム管理者がアプリケーションのログを特別に処理したい場合は、このように構成します。

アプリケーションを介してログをローテーションしないでください。ログをどのように処理するかはユーザーが選択します(SLAに関連する場合があります)。ログのローテーション方法を構成可能にした場合でも、管理者はログの構成方法を学習する必要があります。これにより、不要な冗長性が発生します。

ログファイルに書き込む必要がある場合は、ターゲットシステムのログポリシーを順守し、ログローテーション構成ファイルを提供します。マシンのディスク容量が不足したからといって、アプリケーションがダウンタイムの原因になることを望まないのではないでしょうか。

車輪の再発明の代わりにシステムツールを使用します。アプリケーションでメンテナンスを行う必要がある場合は、アプリケーション内でスケジューラーを使用する必要はありません。メンテナンス用の専用ツールを作成し(モノリシックアプリケーションは'00年代)、cronを利用します。具体的には、対応するファイルを/etc/cron*ディレクトリの1つに追加します。

適切なinitスクリプトを提供します!このようにして、管理者はsystemctlアプリケーションの起動とシャットダウンを管理します。ユーザーにsuする必要がある場合、またはSudo -uを使用して起動時にシェルスクリプトを呼び出す必要がある場合は、かなり面倒です。このスクリプトが@onbootと呼ばれている場合でも、標準からの逸脱は厄介です。起動方法が機能するからといって、それを使用する必要があるという意味ではありません。

SE-Linuxプロファイルを追加するためのボーナスポイント!

言うまでもありませんが、パッケージの設定が間違っていることがよくあります。パッケージをテストしてください!ターゲットOSの最小限のインストールから始めてください。パッケージをインストールし、期待どおりに実行されることを確認します。提供するすべての構成を確認してください。

パッケージを公式のDebianリポジトリに入れることを計画している場合は、しばらく計画する必要があります。Debianが同じくらい安定している理由は、パッケージの要件がかなり厳しく、すべての要件を満たしている場合でも、すべてを実行する必要があるためです。不安定なテストから安定したテストへの道。

正確に

便利だからといって既存のユーザーを使用しないでください。Webアプリケーションを作成する場合は、「Apache」または「www」ユーザーを再利用しないでください。パッケージ専用のユーザーを作成し、このユーザーを対応するグループに追加します

必要最小限のアクセス許可の原則を順守します。バイナリワールドを実行可能にする理由はほとんどなく、ワールド書き込み可能ファイルははるかに少なくなります(extremeセキュリティホール)。ここでよく見られるのは、アプリケーションが実行されない場合にSOで、アクセス許可を[0] 777に設定することです。これにより、すべてのユーザーがファイルに対して変更を加えることができます。バイナリをどのユーザーにも書き込み可能にする理由はほとんどありません。とにかく更新を行うrootは、いつでも何でも書き込むことができます。したがって、バイナリのアクセス許可は0550である必要があります。原則はデータディレクトリなどにも適用されます。ここで時間と労力を費やします。攻撃を成功させるためのベクトルにアプリを使用したくないですか?潜在的なセキュリティリスクでさえ、あなたとあなたの評判に反発する傾向があります。私がする傾向があるのは、すべてのデータファイルを設定することです。アプリケーションのシステムユーザーが書き込む必要のあるファイルの場合は0600、読み取り専用ファイルの場合は0400、バイナリの場合は0500に、次に、グループの詳細な分析を行います。権限は次のようになります。例:グループがWebアプリケーションの個々のテンプレートを変更する場合がありますが、ほとんどの場合、dは変更されません。リソースディレクトリサブツリーの構造。

セキュリティに力を入れれば、信頼が高まります。パッケージは、採用されるかどうかを決定する前に、セキュリティへの影響がチェックされることが多いことに注意してください。

[〜#〜] fhs [〜#〜] (!!)!に準拠し、それでも: /opt/yourapplicationの下で何でもできますが、そうすることは必ずしも良い考えではありません。むしろ、それぞれ/usr/varにインストールします(起動時にアプリケーションが必要ないと仮定します)。

依存関係がある場合は、それらを定義します。単にパッケージが存在すると想定しないでください。

ローカルSMTPサーバーへの依存関係がある場合は、postfixへの依存関係を宣言しないでください。たぶん、管理者はsendmailを好むでしょう(何らかの理由で)。したがって、代わりにmail-transport-agent(Debian)またはmta(RH、iirc)への依存関係を定義します。

結論

これは私が優れたソフトウェアに期待することです。既存のソフトウェアとうまく統合し、冗長構成を学ぶことなく、インストール、保守、構成、および実行を容易にします。パッケージのSELinuxプロファイルを見ると、それは本当にベンダーにボーナスを与えます–プロファイルが極端にずさんでない限り、ベンダーがセキュリティを非常に真剣に受け止めていることを示しています。

3