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- 두 번째 파일 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=andrei루트가 아닌 사용자( )로 응용 프로그램을 실행하고 있지만 응용 프로그램이 http.ListenAndServe(":80", nil)일반적으로 루트 사용자만 수신할 수 있는 권한 있는 포트인 포트 80( )에서 수신을 시도하고 있다는 것입니다.

네가 말할 때:

터미널에서 애플리케이션을 실행하면 모든 것이 잘 작동합니다.

어쨌든, 당신은 그것을 다음과 같이 실행합니까?뿌리? 왜냐하면 나는 그것이 작동하기를 원하기 때문입니다.

다른 포트(권한이 없는 1024보다 큰 포트 번호)를 사용할 수 있는 경우 이것이 루트가 아닌 사용자로 서비스를 실행하는 가장 쉬운 솔루션이 될 것입니다.


또한 유닛 파일의 이 스니펫은 다음과 같습니다.

[Socket]
ListenStream=80
NoDelay=true

이는 실제로 서비스 단위에는 적용되지 않으며 다음에만 적용됩니다.소켓 유닛, 그래서 만들어소켓 활성화작동하려면 이러한 설정을 갖춘 별도의 장치가 필요합니다 MyApp.socket.

그러나 소켓 활성화는 별도의 장치를 만드는 것보다 더 복잡합니다. 왜냐하면 응용 프로그램 자체가 systemd에서 수신 소켓 수신을 지원해야 하기 때문입니다. 예를 들어, C 애플리케이션은 다음을 호출합니다.sd_listend_fds()이를 달성하기 위해 libsystemd에 연결합니다. Go에는 동일한 작업을 수행하는 바인딩이 있을 수 있습니다.코어로스/go-systemd예를 들어, 거기에 일부가 있을 수 있습니다.

소켓 활성화의 장점은 포트 80과 루트가 아닌 사용자를 사용할 수 있다는 점이지만 위에서 언급한 것처럼 애플리케이션을 변경해야 합니다.

관련 정보