Nhầm lẫn bởi các mục ExecStartPre trong tệp đơn vị systemd


23

Tôi có một dịch vụ systemd cần tạo một thư mục /run, nhưng nếu không thì chạy như một người dùng không root. Từ một ví dụ trên blog, tôi đã rút ra giải pháp sau:

[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

Điều kỳ diệu là trong 3 dòng theo nhận xét. Rõ ràng ExecStartPrelà sẽ chạy như root theo cách này, nhưng ExecStartsẽ chạy như người dùng được chỉ định.

Điều này đã dẫn đến 3 câu hỏi mặc dù:

  1. Làm gì -trước mặt /bin/mkdir? Tôi không biết tại sao nó ở đó hoặc nó làm gì.
  2. Khi có nhiều ExecStartPretệp trong một tệp đơn vị, chúng chỉ chạy một cách tuần tự theo thứ tự mà chúng được tìm thấy trong tệp đơn vị? Hoặc một số phương pháp khác?
  3. Đây thực sự là kỹ thuật tốt nhất để thực hiện mục tiêu của tôi là tạo thư mục chạy để người dùng không root có thể sử dụng nó?

Lý do mà ExecStartPrechạy như root là PermissionsStartOnly=truechỉ thị. Nó hạn chế Userchỉ thị cho ExecStartlệnh. Xem freedesktop.org/software/systemd/man/systemd.service.html
cayhorstmann

Câu trả lời:


30

Đối với bất kỳ câu hỏi nào về một chỉ thị systemd, bạn có thể sử dụng man systemd.directivesđể tra cứu trang man ghi lại chỉ thị. Trong trường hợp ExecStartPre=, bạn sẽ thấy nó được ghi lại man systemd.service.

Ở đó, trong các tài liệu cho ExecStartPre=, bạn sẽ thấy nó giải thích rằng "-" hàng đầu được sử dụng để lưu ý rằng thất bại được chấp nhận cho các lệnh này. Trong trường hợp này, nó được dung thứ nếu /run/thingđã tồn tại.

Các tài liệu ở đó cũng giải thích rằng "nhiều dòng lệnh được cho phép và các lệnh được thực thi lần lượt theo thứ tự khác."

Một cải tiến cho phương pháp tạo trước thư mục của bạn là không làm cho nó có thể ghi được trên thế giới khi bạn chỉ cần nó có thể ghi được bởi một người dùng cụ thể. Nhiều quyền hạn chế hơn sẽ được thực hiện với:

 ExecStartPre=-/bin/chown thingUser /run/thing
 ExecStartPre=-/bin/chmod 700       /run/thing

Điều đó làm cho thư mục thuộc sở hữu và có thể truy cập đầy đủ từ một người dùng cụ thể.


Câu trả lời tuyệt vời, cảm ơn bạn về gợi ý systemd.directives, tôi luôn thấy systemd khó tìm ra nơi để đi. Những sự giúp đỡ đó.
Travis Griggs

1
Bạn có lẽ nên bao gồm RuntimeDirectoryRuntimeDirectoryModequá.
JdeBP

2

Trả lời # 3:

Kiểm tra RuntimeDirectory=& RuntimeDirectoryMode=chỉ thị. Tài liệu đầy đủ ở đây . Nhưng tóm lại (sửa đổi một chút thành văn bản, nhưng bản chất vẫn nên):

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.

Vì vậy, để tận dụng điều đó, điều này nên thực hiện mẹo:

[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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.