시스템 서비스 단위 파일에 환경 변수를 동적으로 할당하는 방법이 있습니까?
4개의 GPU가 있는 머신이 있고 각 GPU가 서비스의 여러 인스턴스를 시작하기를 원합니다. 예를 들어:
- gpu_service@1:1.service
- gpu_service@2:1.service
- gpu_service@3:1.서비스
- gpu_service@4:1.서비스
- gpu_service@1:2.service
- gpu_service@2:2.service
- gpu_service@3:2.service
- gpu_service@4:2.service
- 역겨운
따라서 1:1, 2:1 등은 실제로 서비스 단위 파일에서 %i입니다.
서비스를 특정 GPU에 바인딩하기 위해 서비스 실행 파일은 특정 환경 변수를 확인합니다. 예를 들면 다음과 같습니다.
USE_GPU=4
서비스 단위 파일에서 %i를 가져와 일부 (셸) 함수를 통해 실행하여 GPU 번호를 내보낸 다음 그에 따라 USE_GPU 환경 변수를 설정할 수 있는 방법이 있습니까?
/etc/systemd/system/gpu_service@x:y.service/local.conf
가장 중요한 것은 더 많은 인스턴스를 시작하기 위해 여러 파일을 작성하는 번거로움을 원하지 않는다는 것입니다 .
답변1
주의한다면 인스턴스 서비스 파일에 작은 bash 스크립트 시퀀스를 exec 명령으로 통합할 수 있습니다. 예를 들어
ExecStart=/bin/bash -c 'v=%i; USE_GPU=$${v%:*} exec /bin/mycommand'
$$
문자열은 bash에 전달된 결과에서 단일이 되지만 더 중요한 것은 systemd에 의한 보간이 $
중지된다는 것입니다 . ${...}
(이전 버전의 systemd에는 문서화된 사용법이 없었기 $$
때문에 당시에 지원되었는지는 알 수 없습니다.)
답변2
내장된 방법이 없습니다. 서비스가 시작되기 전에 이러한 작업을 수행해야 합니다. 한 가지 방법은 환경 파일에 넣는 것입니다.
[Service]
# Note you need to escape percentage sign
ExecStartPre=/bin/sh -c "my_awesome_parser %%i > /run/gpu_service_%i"
EnvironmentFile=/run/gpu_service_%i
ExecStart=...
답변3
실제로 systemd 단위 파일에서 환경 변수를 설정할 수 있는 것 같습니다...
댓글 작성자가 제안한 대로 해결책은 다음과 같습니다.
시스템 단위에서 환경 변수 사용
환경 지침
systemd에는 실행 프로세스에 대한 환경 변수를 설정하는 환경 지시문이 있습니다. 공백으로 구분된 변수 할당 목록이 필요합니다. 이 옵션은 여러 번 지정할 수 있으며, 이 경우 나열된 모든 변수가 설정됩니다. 동일한 변수를 두 번 설정하면 나중 설정이 이전 설정을 덮어씁니다. 이 옵션에 빈 문자열을 할당하면 환경 변수 목록이 재설정되고 모든 이전 할당이 적용되지 않습니다. 환경 지시어는 etcd2 및 flannel과 같은 내장형 Container Linux 시스템 장치와 함께 사용됩니다.
다음 예에서는 암호화를 사용하도록 etcd2 데몬을 구성할 수 있습니다. etcd2.service에 대한
/etc/systemd/system/etcd2.service.d/30-certificates.conf
드롭인을 생성하세요.[Service] # Client Env Vars Environment=ETCD_CA_FILE=/path/to/CA.pem Environment=ETCD_CERT_FILE=/path/to/server.crt Environment=ETCD_KEY_FILE=/path/to/server.key # Peer Env Vars Environment=ETCD_PEER_CA_FILE=/path/to/CA.pem Environment=ETCD_PEER_CERT_FILE=/path/to/peers.crt Environment=ETCD_PEER_KEY_FILE=/path/to/peers.key
그런 다음 새 환경을 실행
sudo systemctl daemon-reload
하고sudo systemctl restart etcd2.service
etcd2 데몬에 적용하십시오.
인용된 텍스트는 다음 URL에서 가져왔습니다. https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html
답변4
EnvironmentFile
변수가 있는 env 파일을 가리키는 지시문을 사용합니다 . 이 파일은 ExecStartPre
실제 서비스가 시작되기 전에 명령어에 의해 생성됩니다. ExecStart
지시문 내에서 변수에 액세스할 수 있습니다 ${GPU_COUNT}
.
[Unit]
Description=Dynamic variables in systemd units
[Service]
Type=simple
EnvironmentFile=-/tmp/gpu.env
ExecStartPre=sh -c 'printf "%%s\n" GPU_COUNT=$( (...) ) > /tmp/gpu.env'
ExecStart=(...)
ExecStartPost=sh -c 'rm /tmp/gpu.env'
file path 접두어를 붙여야 합니다 -
. 이렇게 하면 systemd는 초기 검사 중에 파일이 존재하지 않는다는 사실을 무시하게 됩니다. 나중에 이 ExecStartPre
명령은 env 파일을 생성합니다. 또 다른장치 상태파일 위치는 다시 평가되고(아직 이전에도 ExecStart
) systemd는 변수가 있는 경우 해당 변수를 로드합니다. man systemd.exec
설명은 다음과 같습니다.
The files listed with this directive will be read shortly before the process is executed (more specifically, after all processes from a previous unit state terminated. This means you can generate these files in one unit state, and read it with this option in the next. The files are read from the file system of the service manager, before any file system changes like bind mounts take place).