DebianまたはUbuntuでsystemdを使用して単純なGo / Golangサーバーを起動する

DebianまたはUbuntuでsystemdを使用して単純なGo / Golangサーバーを起動する

systemdを使って次のGolangコードを実行したいと思います。

...

func main() {
  // main routes
  http.HandleFunc("/", hello)
  log.Fatalln(http.ListenAndServe(":80", nil))
}

func hello(w http.ResponseWriter, r *http.Request) {
  fmt.Fprint(w, "Hello")
}

このコードが使用されますgo build

生成されたバイナリ名: MyApp

パス:/home/andrei/MyApp/MyApp- 2番目のファイルMyAppはバイナリファイルです。

/lib/systemd/systemその中に内容の入ったファイルを入れました。MyApp.service

[Unit]
Description=MyApp service
After=network.target

[Socket]
ListenStream=80
NoDelay=true

[Service]
Type=simple
Restart=on-failure
RestartSec=3
User=andrei
Group=andrei

WorkingDirectory=/home/andrei/MyApp
ExecStart=/home/andrei/MyApp/MyApp

[Install]
WantedBy=multi-user.target

Ubuntuは次のコマンドを実行します(Debianではsudoを使用)。

sistemctl start MyApp.service
sistemctl status MyApp.service

私は出力を取得します:

● MyApp.service - MyApp service
Loaded: loaded (/lib/systemd/system/MyApp.service; disabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Wed 2018-11-14 11:30:45 UTC; 1s ago
Process: 14883 ExecStart=/home/andrei/MyApp/MyApp (code=exited, status=1/FAILURE)
Main PID: 14883 (code=exited, status=1/FAILURE)

Nov 14 11:30:45 andrei systemd[1]: MyApp.service: Main process exited, code=exited, status=1/FAILURE
Nov 14 11:30:45 andrei systemd[1]: MyApp.service: Failed with result 'exit-code'.

NOTE:

端末でアプリケーションを実行すると、すべてがうまく機能します。

systemdを使用してアプリケーションを起動するには?

Update:

次の操作で動作します。

sudo setcap CAP_NET_BIND_SERVICE=+eip /home/andrei/MyApp/MyApp

より良いユニットファイルが役に立ちます。動作させる必要はありません。

[Unit]
Description=MyApp service
After=network.target

[Service]
Type=simple
Restart=always
User=andrei
Group=andrei
WorkingDirectory=/home/andrei/MyApp
ExecStart=/home/andrei/MyApp/MyApp

# make sure log directory exists and owned by syslog
PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p /var/log/sleepservice
ExecStartPre=/bin/chown syslog:adm /var/log/sleepservice
ExecStartPre=/bin/chmod 755 /var/log/sleepservice
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=sleepservice

[Install]
WantedBy=multi-user.target

それでは、次のように動作させます。

sudo systemctl daemon-reload
sudo systemctl start MyApp.service
sudo systemctl enable MyApp.service # app will start on OS restart
sudo journalctl -f -u MyApp.service # provide information about the app

ベストアンサー1

現在遭遇している問題は、User=andreirootではなくユーザー()でアプリケーションを実行していますが、アプリケーションが通常roothttp.ListenAndServe(":80", nil)ユーザーだけをリッスンできる特権ポートであるポート80()でリッスンしようとしていることです。

あなたが言うとき:

端末でアプリケーションを実行すると、すべてがうまく機能します。

とにかく、あなたはそれを次のように実行しますか??なぜなら、それがうまくいきたいからです。

別のポート(許可なしで1024より大きいポート番号)が利用可能な場合、これはroot以外のユーザーとしてサービスを実行する最も簡単なソリューションです。


また、ユニットファイルのこのスニペットは次のとおりです。

[Socket]
ListenStream=80
NoDelay=true

これは実際にはサービスユニットには適用されず、次にのみ適用されます。ソケットユニットだから、ソケットの有効化機能するには、これらの設定を備えた別々のデバイスが必要ですMyApp.socket

しかし、ソケットの起動は、別々のデバイスを作成するよりも複雑です。なぜなら、アプリケーション自体がsystemdで受信ソケット受信をサポートする必要があるからです。たとえば、C アプリケーションは次を呼び出します。sd_listend_fds()これを達成するためにlibsystemdに接続します。 Goには同じことを行うバインディングがあるかもしれません。コアロス/go-systemdたとえば、そこにいくつかあるかもしれません。

ソケットを有効にする利点は、ポート80とroot以外のユーザーを使用できることですが、上記のようにアプリケーションを変更する必要があります。

おすすめ記事