시스템 서비스에서 환경 변수를 설정하는 방법은 무엇입니까?


162

systemd를 사용 하는 아치 리눅스 시스템을 가지고 있으며 자체 서비스를 만들었습니다. 구성 서비스는 /etc/systemd/system/myservice.service다음과 같습니다.

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

이제 환경 변수를 설정하고 싶습니다 /bin/myforegroundcmd. 어떻게합니까?

답변:


197

시간이 바뀌고 모범 사례도 변경됩니다.

현재 이 작업을 수행하는 가장 좋은 방법은 다음을 수행하는 것입니다 systemctl edit myservice당신을 위해 재정의 파일을 생성 할, 또는 기존의 것을 편집 할 수 있습니다.

일반 설치에서는 디렉토리가 작성 /etc/systemd/system/myservice.service.d되고 해당 디렉토리 내에 이름이 .conf(일반적으로 override.conf)로 끝나는 파일이 작성되며이 파일에서 분배로 제공된 장치의 일부를 추가하거나 대체 할 수 있습니다.

예를 들어 파일에서 /etc/systemd/system/myservice.service.d/myenv.conf:

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"

또한 디렉토리가 존재하고 비어 있으면 서비스가 비활성화됩니다! 디렉토리에 무언가를 넣지 않으려면 존재하지 않는지 확인하십시오.


참고로 옛날 방식은 다음과 같습니다.

권장되는 방법/etc/sysconfig/myservice변수가 포함 된 파일 을 만든 다음로로드하는 것입니다 EnvironmentFile.

자세한 내용 은 시스템 스크립트 작성 방법대한 Fedora의 설명서를 참조하십시오 .


4
나는 생각 sysconfig경로가 페도라에 고유하지만 문제는 아치 리눅스에 관한 것입니다. paluh의 답변이 더 흥미 롭습니다
Ludovic Kuty

1
/etc/sysconfigFedora 전용입니다. AFAIR Arch Linux는 구성 파일 /etc을 Fedora 특정 위치 가 아닌 패키지 특정 위치에 두도록 추진했습니다 . 마찬가지로 /etc/myservice.conf, 여기에 올바른 방법으로하지 않는 것 여분의 파일을 사용하지만.
Michał Górny

5
아니, 아니. / etc / sysconfig는 권장되지 않습니다. 데비안의 / etc / default / *와 함께 의미가 없으므로 이름은 의미가 없으며 이전 버전과의 호환성을 위해서만 의미가 있습니다 (모든 / etc는 / etc /가 아니라 시스템 구성에 대한 것입니다 sysconfig 및 / etc / defaults는 기본값이 아닌 대체 용입니다. 정의를 유닛 파일에 직접 넣거나 가능하지 않은 경우 패키지 특정 위치가있는 환경 파일에 넣으십시오 (Michał의 의견과 같이).
zbyszek

1
@FrederickNord DJANGO_SETTINGS_MODULE=project.settings한 줄에 하나씩 변수 = 값 쌍 입니다.
Michael Hampton

1
@MichaelHampton "현재 최상의 방법"에 대한 문서 링크를 추가 할 수 있습니까?
jb.

77

대답은 변수가 일정 해야하는지 (즉, 사용자가 장치를 가져 와서 수정해서는 안 됨) 또는 변수 (사용자가 설정해야한다고 가정)에 따라 다릅니다.

그것이 당신의 지역 단위이기 때문에, 경계는 상당히 흐릿하고 어느 쪽이든 작동합니다. 그러나 배포를 시작했는데로 끝나면 /usr/lib/systemd/system이것이 중요해집니다.

상수 값

인스턴스 당 값을 변경할 필요가없는 경우 선호되는 방법은 Environment=단위 파일에 직접 로 배치하는 것입니다 .

[Unit]
Description=My Daemon

[Service]
Environment="FOO=bar baz"
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

이것의 장점은 변수가 유닛과 함께 단일 파일로 유지된다는 것입니다. 따라서 단위 파일이 시스템간에보다 쉽게 ​​이동할 수 있습니다.

변수 값

그러나 sysadmin이 환경 변수의 값을 로컬로 변경해야하는 경우 위의 솔루션이 제대로 작동하지 않습니다. 보다 구체적으로, 단위 파일이 업데이트 될 때마다 새 값을 설정해야합니다.

이 경우 추가 파일이 사용됩니다. 방법 — 일반적으로 배포 정책에 따라 다릅니다.

특히 흥미로운 해결책 중 하나는 /etc/systemd/system/myservice.service.d디렉토리 를 사용하는 것 입니다. 다른 솔루션과 달리이 디렉토리는 시스템 자체에서 지원되므로 배포 별 경로가 없습니다.

이 경우 다음과 같이 파일을 배치하면 /etc/systemd/system/myservice.service.d/local.conf단위 파일의 누락 된 부분이 추가됩니다.

[Service]
Environment="FOO=bar baz"

그 후, systemd는 서비스를 시작할 때 두 파일을 병합합니다 (두 파일 systemctl daemon-reload중 하나를 변경 한 후에 기억하십시오 ). 그리고이 경로는 systemd에서 직접 사용하기 때문에 이것을 사용하지 않습니다 EnvironmentFile=.

영향을받는 일부 시스템에서만 값을 변경해야하는 경우 두 솔루션을 결합하여 장치에서 직접 기본값을 제공하고 다른 파일에서 로컬 재정의를 제공 할 수 있습니다.


systemctl daemon-reload시스템을 다시로드하는 명령입니다
Dmitry Buzolin

EnvironmentFile=값이 비밀번호와 같은 비밀 일 때 더 좋습니다. 자세한 내용은 내 답변 을 참조하십시오.
돈 커크비


17

MichaelMichał 의 답변 은 도움이되며 시스템 서비스에 환경 변수를 설정하는 방법에 대한 원래의 질문에 답변합니다. 그러나 환경 변수의 일반적인 용도 중 하나 는 실수로 애플리케이션 코드를 사용하여 소스 제어에 전념하지 않는 위치에 비밀번호와 같은 민감한 데이터를 구성하는 것입니다.

그렇기 때문에 환경 변수를 서비스에 전달 하려면 장치 구성 파일에서 사용 하지 마십시오Environment= . EnvironmentFile=서비스 계정 (및 루트 액세스 권한이있는 사용자) 만 읽을 수있는 다른 구성 파일을 사용하십시오 .

장치 구성 파일의 세부 사항은이 명령으로 모든 사용자에게 표시됩니다.

systemctl show my_service

구성 파일을 /etc/my_service/my_service.conf넣고 비밀을 거기에 넣었습니다.

MY_SECRET=correcthorsebatterystaple

그런 다음 서비스 단위 파일에서 다음을 사용했습니다 EnvironmentFile=.

[Unit]
Description=my_service

[Service]
ExecStart=/usr/bin/python /path/to/my_service.py
EnvironmentFile=/etc/my_service/my_service.conf
User=myservice

[Install]
WantedBy=multi-user.target

그 체크 ps auxe하는 환경 변수를 볼 수 있으며, 다른 사용자가 액세스 할 수 없습니다 /proc/*/environ. 물론 자신의 시스템을 확인하십시오.


8

Michael은 하나의 깨끗한 솔루션을 제공했지만 스크립트에서 env 변수를 업데이트하려고했습니다. 불행히도 시스템 단위 파일에서는 bash 명령을 실행할 수 없습니다. 다행히도 ExecStart 내에서 bash를 트리거 할 수 있습니다.

http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=systemd.service&sect=5

이 설정은 쉘 명령 행을 직접 지원하지 않습니다. 쉘 명령 행을 사용하려면 어떤 종류의 쉘 구현으로 명시 적으로 전달해야합니다.

이 경우의 예는 다음과 같습니다.

[Service]
ExecStart=/bin/bash -c "ENV=`script`; /bin/myforegroundcmd"

7
이것은 여러 가지 이유로 작동하지 않습니다 ( "원샷"서비스가 아니라면 무의미합니다). 나는 다음을 작동시킬 수 있었다 /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. -a(당신이 모든 변수를 앞에하지 않으려면 보장하지만이 환경은 하위 프로세스에 수출되고 있습니다 whateverexport)
Otheus

왜 작동하지 않습니까? 항상 스크립트 실행을 포함한 전체 명령을 트리거해야합니까?
user1830432

어쩌면 ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd이 경우에는 조금 더 나은 솔루션입니다.
kstep

@Otheus : Tomcat 8 Unit 파일을 만들어야 할 때 저장되는 훌륭한 답변.
Daniel

1
시스템 서비스 파일을 "in"bash 명령을 실행하는 방법이 있습니다. 이 링크를 참조하십시오 : coreos.com/os/docs/latest/…
Mark Lakata
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.