하나의 시스템 서비스 파일로 N 프로세스 시작


36

https://gist.github.com/thomasfr/9707568 ssh 터널을 유지하기 위해 autossh를 시작하는이 시스템 서비스 파일을 찾았습니다.

[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를 대체해야하는 이유는 무엇입니까?

몇 달 후이 루프와 템플릿은 구성을 자동화하는 도구로 해결해야한다고 생각합니다. 나는 지금 위키 백과 에서이 목록의 도구 하나를 사용 합니다.


다시 말해, 구성 관리 시스템을 사용하여이 작업을 수행하기 위해 거의 동일한 서비스 파일을 여러 개 생성한다는 말입니까? 흠. 이러한 대부분의 문제와 마찬가지로, 이들을 구분하는 명확한 구분선은 없습니다.
pgoetz

@pgoetz 설정 관리는 여전히 나에게는 새로운 것이지만이 질문의 주제를 보면 이점이 있습니다. 설정 관리 결과를 보면 시스템화 된 서비스 파일을 알고있는 모든 사람들이 그것을 이해할 것입니다 : 단순하고 간단한 서비스 파일 . 지식은 systemd뿐만 아니라 / etc의 모든 구성에 사용될 수 있기 때문에 구성 관리 시스템을 배우고 사용하는 것이 더 합리적이라고 생각합니다.
guettli

답변:


47

단위 파일 당 변경 되는 것이 remote.example.com부분 이라고 가정 하면 Instantiated Service를 사용할 수 있습니다 .

로부터 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이와 같은 경우에 가장 잘 작동합니다.


와, 체계적입니다.
guettli

부팅 할 때를 포함하여 부팅시 자동으로 시작하는 방법을 보여주지 않습니다.
Craig Hicks

Systemd를 사용하면 enable부팅시 장치 / 서비스가 시작됩니다.
GregL

인스턴스를 독립적으로 활성화 / 비활성화 할 수 있습니까?
Soumya Kanti

네, 그게 당신이 그들을 활성화 / 비활성화 할 때하고있는 일입니다.
GregL

15

여기 내가 찾던 파이썬 예제가 있습니다. @서비스 파일 이름에 당신은 N 프로세스를 시작할 수 있습니다 :

$ cat /etc/systemd/system/my-worker@.service

[Unit]
Description=manages my worker service, instance %i
After=multi-user.target

[Service]
PermissionsStartOnly=true
Type=idle
User=root
ExecStart=/usr/local/virtualenvs/bin/python /path/to/my/script.py
Restart=always
TimeoutStartSec=10
RestartSec=10

그것을 부르는 다양한 방법

예를 들어 다음과 같이 다양한 개수를 활성화합니다.

  • 30 명의 노동자를 가능하게하십시오 :

    sudo systemctl enable my-worker\@{1..30}.service
    
  • 2 명의 노동자를 가능하게하십시오 :

    sudo systemctl enable my-worker\@{1..2}.service
    

그런 다음 다시로드하십시오 :

sudo systemctl daemon-reload

이제 다양한 방법으로 시작 / 중지 할 수 있습니다.

  • 시작 1 :

    sudo systemctl start my-worker@2.service
    
  • 여러 개 시작 :

    sudo systemctl start my-worker@{1..2}
    
  • 여러 중지 :

    sudo systemctl stop my-worker@{1..2}
    
  • 상태를 확인하세요:

    sudo systemctl status my-worker@1
    

업데이트 : 인스턴스를 하나의 서비스로 관리하려면 다음과 같이 할 수 있습니다.

/etc/systemd/system/some-worker@.service :

[Unit]
Description=manage worker instances as a service, instance %i
Requires=some-worker.service
Before=some-worker.service
BindsTo=some-worker.service

[Service]
PermissionsStartOnly=true
Type=idle
User=root
#EnvironmentFile=/etc/profile.d/optional_envvars.sh
ExecStart=/usr/local/virtualenvs/bin/python /path/to/my/script.py
TimeoutStartSec=10
RestartSec=10

[Install]
WantedBy=some-worker.service

/usr/bin/some-worker-start.sh :

#!/bin/bash
systemctl start some-worker@{1..10}

/etc/systemd/system/some-worker.service :

[Unit]
Description=manages some worker instances as a service, instance

[Service]
Type=oneshot
ExecStart=/usr/bin/sh /usr/bin/some-worker-start.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

이제 모든 인스턴스를 관리 할 수 ​​있습니다 sudo systemctl some-worker (start|restart|stop)

여기에 대한 상용구가 있습니다 script.py.

#!/usr/bin/env python

import logging


def worker_loop():
    shutdown = False
    while True:

        try:
            if shutdown:
                break

            # Your execution logic here.
            # Common logic - i.e. consume from a queue, perform some work, ack message
            print("hello world")

        except (IOError, KeyboardInterrupt):
            shutdown = True
            logging.info("shutdown received - processing will halt when jobs complete")
        except Exception as e:
            logging.exception("unhandled exception on shutdown. {}".format(e))


if __name__ == '__main__':
    worker_loop()

@radek : 내가 이해하지 못하는 두 가지 : 첫째, % i는 유닛 파일의 설명에만 사용됩니다. start 명령은 무엇을 시작해야하는지 어떻게 알 수 있습니까? 둘째, systemctl some-worker (start|restart|stop)어떤 인스턴스에서 작업해야하는지 어떻게 알 수 있습니까?
U. Windl

% i는 서비스 파일 이름에서 @의 출력입니다. 두 번째 부분은 이미 답변에 설명되어 있습니다 Now you can start/stop then in various ways.
radtek

대본이 없으면 그의 대답이 불완전하다고 생각합니다. 대부분의 "마법"은 누락 된 스크립트 내에서 수행됩니다.
U. Windl

실제로 여기에 완전한 솔루션을 제공했습니다. 어떤 "스크립트"를 언급하고 있습니까? /path/to/my/script.py는 당신이 원하는 무엇이든 될 수 있습니다. 원한다면 "hello world"입니다. 킬 (kill) 신호를 수신 할 때까지 계속 작동합니다. 이 질문은 파이썬에만 국한되지 않습니다.
radtek

한 번에 여러 개를 시작할 수 있습니까? 마음이 날

1

GregL의 답변이 저에게 큰 도움이되었습니다. 다음은 기어 맨 작업 서버에 대한 위의 예를 사용하여 코드에서 사용한 단위 템플릿의 예입니다. 이 하나의 템플릿을 사용하여 X 량의 "작업자"를 만들 수있는 쉘 스크립트를 만들었습니다.

[Unit]
Description=az gearman worker
After=gearman-job-server.service

[Service]
PIDFile=/var/run/gearman_worker_az%i.pid
Type=simple
User=www-data
WorkingDirectory=/var/www/mysite.com/jobs/
ExecStart=/usr/bin/php -f gearman_worker_az.php > /dev/null 2>&1
Restart=on-success
KillMode=process

[Install]
WantedBy=multi-user.target
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.