Daemon

使用一個 systemd 服務文件啟動 N 個程序

  • March 22, 2020

我發現這個 systemd 服務文件啟動 autossh 以保持 ssh 隧道:https ://gist.github.com/thomasfr/9707568

[Unit]
Description=Keeps a tunnel to 'remote.example.com' open
After=network.target

[Service]
User=autossh
# -p [PORT]
# -l [user]
# -M 0 --> no monitoring
# -N Just open the connection and do nothing (not interactive)
# LOCALPORT:IP_ON_EXAMPLE_COM:PORT_ON_EXAMPLE_COM
ExecStart=/usr/bin/autossh -M 0 -N -q -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -p 22 -l autossh remote.example.com -L 7474:127.0.0.1:7474 -i /home/autossh/.ssh/id_rsa

[Install]
WantedBy=multi-user.target

有沒有辦法配置 systemd 在一個服務中啟動多個隧道。

我不想創建 N 個系統服務文件,因為我想避免複製+粘貼。

除了“remote.example.com”將被其他主機名替換之外,所有服務文件都是相同的。

1.5年後…

我大約在 1.5 年前問過這個問題。

我的想法變了。是的,很好,你可以用 systemd 做到這一點,但我將來會使用配置管理。

為什麼 systemd 應該實現模板語言並替換 %h?..我認為這沒有任何意義。

幾個月後,我認為這種循環和模板應該在不同的層面上解決。我現在會為此使用 Ansible 或 TerraForm。

好吧,假設每個單元文件唯一remote.example.com改變的是零件,您可以使用實例化 服務

systemd.unit手冊頁:

可選地,可以在執行時從模板文件中實例化單元。這允許從單個配置文件創建多個單元。如果 systemd 查找單元配置文件,它將首先在文件系統中搜尋文字單元名稱。如果這沒有成功並且單元名稱包含一個“@”字元,systemd 將尋找一個具有相同名稱但刪除了實例字元串(即“@”字元和後綴之間的部分)的單元模板。範例:如果請求服務 getty@tty3.service 並且沒有找到該名稱的文件,systemd 將查找 getty@.service 並從該配置文件中實例化一個服務,如果找到的話。

基本上,您創建一個單元文件,其中包含一個變數(通常是%i),其中出現差異,然後在您“啟用”該服務時將它們連結起來。

例如,我有一個名為的單元文件/etc/systemd/system/autossh@.service,如下所示:

[Unit]
Description=AutoSSH service for ServiceABC on %i
After=network.target

[Service]
Environment=AUTOSSH_GATETIME=30 AUTOSSH_LOGFILE=/var/log/autossh/%i.log AUTOSSH_PIDFILE=/var/run/autossh.%i.pid
PIDFile=/var/run/autossh.%i.pid
#Type=forking
ExecStart=/usr/bin/autossh -M 40000 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC %i

[Install]
WantedBy=multi-user.target

然後我啟用了

[user@anotherhost ~]$ sudo systemctl enable autossh@somehost.example.com
ln -s '/etc/systemd/system/autossh@.service' '/etc/systemd/system/multi-user.target.wants/autossh@somehost.example.com.service'

並且可以互動

[user@anotherhost ~]$ sudo systemctl start autossh@somehost.example.com
[user@anotherhost ~]$ sudo systemctl status autossh@somehost.example.com
autossh@somehost.example.service - AutoSSH service for ServiceABC on somehost.example
  Loaded: loaded (/etc/systemd/system/autossh@.service; enabled)
  Active: active (running) since Tue 2015-10-20 13:19:01 EDT; 17s ago
Main PID: 32524 (autossh)
  CGroup: /system.slice/system-autossh.slice/autossh@somehost.example.com.service
          ├─32524 /usr/bin/autossh -M 40000 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC somehost.example.com
          └─32525 /usr/bin/ssh -L 40000:127.0.0.1:40000 -R 40000:127.0.0.1:40001 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC somehost.example.com

Oct 20 13:19:01 anotherhost.example.com systemd[1]: Started AutoSSH service for ServiceABC on somehost.example.com.
[user@anotherhost ~]$ sudo systemctl status autossh@somehost.example.com
[user@anotherhost ~]$ sudo systemctl status autossh@somehost.example.com
autossh@somehost.example.com.service - AutoSSH service for ServiceABC on somehost.example.com
  Loaded: loaded (/etc/systemd/system/autossh@.service; enabled)
  Active: inactive (dead) since Tue 2015-10-20 13:24:10 EDT; 2s ago
 Process: 32524 ExecStart=/usr/bin/autossh -M 40000 -NR 5000:127.0.0.1:5000 -i /opt/ServiceABC/.ssh/id_rsa_ServiceABC -l ServiceABC %i (code=exited, status=0/SUCCESS)
Main PID: 32524 (code=exited, status=0/SUCCESS)

Oct 20 13:19:01 anotherhost.example.com systemd[1]: Started AutoSSH service for ServiceABC on somehost.example.com.
Oct 20 13:24:10 anotherhost.example.com systemd[1]: Stopping AutoSSH service for ServiceABC on somehost.example.com...
Oct 20 13:24:10 anotherhost.example.com systemd[1]: Stopped AutoSSH service for ServiceABC on somehost.example.com.

如您所見,%i單元文件中的所有實例都被替換為somehost.example.com.

不過,您可以在單元文件中使用更多的說明符,但我發現%i在這種情況下效果最好。

引用自:https://serverfault.com/questions/730239