에 디렉토리를 생성해야 하는 시스템 서비스가 있지만 /run
루트가 아닌 사용자로 실행합니다. 블로그 예제에서 다음과 같은 해결책을 생각해 냈습니다.
[Unit]
Description=Startup Thing
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 -u /opt/thing/doStartup
WorkingDirectory=/opt/thing
StandardOutput=journal
User=thingUser
# Make sure the /run/thing directory exists
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /run/thing
ExecStartPre=/bin/chmod -R 777 /run/thing
[Install]
WantedBy=multi-user.target
마법은 주석 다음 세 줄에 있습니다. 분명히 ExecStartPre
이런 식으로 루트로 실행되지만 ExecStart
지정된 사용자로 실행됩니다.
그러나 이로 인해 다음과 같은 3가지 문제가 발생합니다.
-
앞부분은 무엇을 하는가/bin/mkdir
? 그게 왜 거기 있는지, 무슨 일을 하는지 모르겠어요.- 유닛 파일에 '가 여러 개 있는 경우
ExecStartPre
유닛 파일에 있는 순서대로 순차적으로 실행됩니까? 아니면 다른 방법? - 이것이 루트가 아닌 사용자가 사용할 수 있도록 실행 디렉터리를 생성하려는 목표를 달성하는 데 실제로 가장 좋은 기술입니까?
답변1
systemd 지시어에 대한 질문이 있는 경우 man systemd.directives
해당 지시어를 설명하는 매뉴얼 페이지를 찾아보세요. 의 경우 ExecStartPre=
에 설명되어 있습니다 man systemd.service
.
의 문서에는 ExecStartPre=
이러한 명령이 실패를 허용할 수 있음을 나타내기 위해 앞에 "-"가 사용된다는 설명이 나와 있습니다. 이 경우 /run/thing
이미 존재하는 경우에는 허용됩니다.
문서에는 "여러 명령줄이 허용되며 명령이 순차적으로 실행됩니다"라고 설명되어 있습니다.
미리 생성된 디렉터리 접근 방식에 대한 개선 사항은 특정 사용자만 쓸 수 있어야 하는 디렉터리를 누구나 쓸 수 있도록 만들지 않는 것입니다. 다음을 통해 더 제한된 권한을 달성할 수 있습니다.
ExecStartPre=-/bin/chown thingUser /run/thing
ExecStartPre=-/bin/chmod 700 /run/thing
이렇게 하면 특정 사용자가 디렉터리를 소유하고 완전히 액세스할 수 있게 됩니다.
답변2
답변 #3:
보기 RuntimeDirectory=
및 RuntimeDirectoryMode=
지침. 전체 문서여기. 그러나 요약하면(약간 수정된 텍스트이지만 본질은 유지되어야 함):
RuntimeDirectory=
This option take a whitespace-separated list of directory names. The
specified directory names must be relative, and may not include "..". If
set, one or more directories by the specified names will be created
(including their parents) below /run (for system services) or below
$XDG_RUNTIME_DIR (for user services) when the unit is started. Also, the
$RUNTIME_DIRECTORY environment variable is defined with the full path of
directories. If multiple directories are set, then in the environment
variable the paths are concatenated with colon (":").
The innermost subdirectories are removed when the unit is stopped. It is
possible to preserve the specified directories in this case if
RuntimeDirectoryPreserve= is configured to restart or yes. The innermost
specified directories will be owned by the user and group specified in
User= and Group=.
If the specified directories already exist and their owning user or group
do not match the configured ones, all files and directories below the
specified directories as well as the directories themselves will have their
file ownership recursively changed to match what is configured. As an
optimization, if the specified directories are already owned by the right
user and group, files and directories below of them are left as-is, even if
they do not match what is requested. The innermost specified directories
will have their access mode adjusted to the what is specified in
RuntimeDirectoryMode=.
Use RuntimeDirectory= to manage one or more runtime directories for the
unit and bind their lifetime to the daemon runtime. This is particularly
useful for unprivileged daemons that cannot create runtime directories in
/run due to lack of privileges, and to make sure the runtime directory is
cleaned up automatically after use. For runtime directories that require
more complex or different configuration or lifetime guarantees, please
consider using tmpfiles.d(5).
RuntimeDirectoryMode=
Specifies the access mode of the directories specified in
RuntimeDirectory= as an octal number. Defaults to 0755. See "Permissions"
in path_resolution(7) for a discussion of the meaning of permission bits.
따라서 이를 활용하려면 다음과 같은 트릭을 수행해야 합니다.
[Unit]
Description=Startup Thing
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 -u /opt/thing/doStartup
WorkingDirectory=/opt/thing
StandardOutput=journal
User=thingUser
# Make sure the /run/thing directory exists
PermissionsStartOnly=true
RuntimeDirectory=thing
RuntimeDirectoryMode=0777
[Install]
WantedBy=multi-user.target