在服务启动期间尝试安装外部 USB 驱动器的脚本出现错误:
sudo:有效 uid 不为 0,/usr/bin/sudo 是否位于设置了“nosuid”选项的文件系统上或没有 root 权限的 NFS 文件系统上?
(请注意,挂载操作必须是同步的,因此将其放在服务之外的其他位置ExecStartPre
是不够的。挂载必须是成功服务启动的硬依赖项。规则:如果挂载因任何原因失败,则服务不会稍后我将开始处理通知。)
这是我的服务配置,在用户上下文中运行admin
:
### Editing /etc/systemd/system/[email protected]/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
ExecStartPre=/usr/local/bin/mount-sync-drive.sh
### Lines below this comment will be discarded
### /lib/systemd/system/[email protected]
# [Unit]
# Description=Syncthing - Open Source Continuous File Synchronization for %I
# Documentation=man:syncthing(1)
# After=network.target
# StartLimitIntervalSec=60
# StartLimitBurst=4
#
# [Service]
# User=%i
# ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0 --home=/media/pi/MyBook/.config/syncthing
# Restart=on-failure
# RestartSec=1
# SuccessExitStatus=3 4
# RestartForceExitStatus=3 4
#
# # Hardening
# ProtectSystem=full
# PrivateTmp=true
# SystemCallArchitectures=native
# MemoryDenyWriteExecute=true
# NoNewPrivileges=true
#
# # Elevated permissions to sync ownership (disabled by default),
# # see https://docs.syncthing.net/advanced/folder-sync-ownership
# #AmbientCapabilities=CAP_CHOWN CAP_FOWNER
#
# [Install]
# WantedBy=multi-user.target
...和我的脚本:
#!/bin/bash
exec &>> /var/log/syncthing.log
echo ""
date
# Check if /dev/sda1 is already mounted
if ! grep -qs '/dev/sda1' /proc/mounts; then
# Mount /dev/sda1 to /media/pi/MyBook
echo "Mounting /dev/sda1 to /media/pi/MyBook"
sudo mount -v /dev/sda1 /media/pi/MyBook
fi
当我手动运行脚本时admin
,驱动器安装得很好:
pi@RPI:~ $ mount | grep sda1
pi@RPI:~ $ sudo -u admin /usr/local/bin/mount-sync-drive.sh
mount: /dev/sda1 mounted on /media/pi/MyBook.
pi@RPI:~ $ mount | grep sda1
/dev/sda1 on /media/pi/MyBook type ext4 (rw,relatime)
以下是 的内容syncthing.log
:
Wed 22 Feb 15:57:43 AKST 2023
Mounting /dev/sda1 to /media/pi/MyBook
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
Wed 22 Feb 15:57:44 AKST 2023
Mounting /dev/sda1 to /media/pi/MyBook
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
Wed 22 Feb 15:57:45 AKST 2023
Mounting /dev/sda1 to /media/pi/MyBook
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
Wed 22 Feb 15:57:46 AKST 2023
Mounting /dev/sda1 to /media/pi/MyBook
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
这是服务启动错误(journalctl
没有透露更多信息):
pi@RPI:~ $ sudo systemctl status [email protected]
● [email protected] - Syncthing - Open Source Continuous File Synchronization for admin
Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/[email protected]
└─override.conf
Active: failed (Result: exit-code) since Tue 2023-02-21 17:23:14 AKST; 33s ago
Docs: man:syncthing(1)
Process: 959 ExecStartPre=/usr/local/bin/mount-sync-drive.sh (code=exited, status=1/FAILURE)
CPU: 53ms
Feb 21 17:23:14 RPI systemd[1]: [email protected]: Scheduled restart job, restart counter is at 4.
Feb 21 17:23:14 RPI systemd[1]: Stopped Syncthing - Open Source Continuous File Synchronization for admin.
Feb 21 17:23:14 RPI systemd[1]: [email protected]: Start request repeated too quickly.
Feb 21 17:23:14 RPI systemd[1]: [email protected]: Failed with result 'exit-code'.
Feb 21 17:23:14 RPI systemd[1]: Failed to start Syncthing - Open Source Continuous File Synchronization for admin.
如果我错了,请纠正我,但我相信我已经排除了mount
错误消息中指出的所有可能性:
1. 文件系统上的 /usr/bin/sudo 设置了 'nosuid' 选项:
pi@RPI:~ $ mount | grep nosuid
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,size=186292k,nr_inodes=819200,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime)
fusectl on /sys/fs/fuse/connections type fusectl (rw,nosuid,nodev,noexec,relatime)
configfs on /sys/kernel/config type configfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=93144k,nr_inodes=23286,mode=700,uid=1000,gid=1000)
2. 是具有 NFS 文件系统且没有 root 权限的文件系统上的 /usr/bin/sudo:
pi@RPI:~ $ df -T /usr/bin/sudo
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/root ext4 30343244 4241732 24811444 15% /
我已admin
使用以下命令添加到 sudoers 文件visudo
并重新启动:
admin ALL=(ALL) NOPASSWD: /bin/mount
非常奇怪的是我有另一个类似的系统运行得很好。我已经检查并仔细检查了所有配置,它们是相同的。
这是什么意思,sudo: effective uid is not 0
以及如何解决它?
- 编辑 -
@ajgringo619
根据评论中的问题:
pi@RPI:~ $ sudo -lU admin
Matching Defaults entries for admin on RPI:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, env_keep+=NO_AT_BRIDGE, env_keep+="http_proxy
HTTP_PROXY", env_keep+="https_proxy HTTPS_PROXY", env_keep+="ftp_proxy FTP_PROXY", env_keep+=RSYNC_PROXY, env_keep+="no_proxy NO_PROXY"
User admin may run the following commands on RPI:
(ALL : ALL) ALL
(ALL) NOPASSWD: /bin/mount
- 编辑 -
roaima
根据评论中的问题:
pi@RPI:~ $ ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 178432 Jan 14 04:29 /usr/bin/sudo
答案1
您的脚本有if ! grep -qs '/dev/sda1' /proc/mounts; then
,我认为这是为了解决为每个实例运行此脚本的问题[email protected]
。如果另一个实例正在运行(或过去运行过),则挂载将已经存在,因此此检查是必要的,否则您ExecStartPre=
将失败。
我的另一个答案描述了如何sudo
从脚本中删除,但另一个解决方案是用 systemd 的内置mount
单元替换脚本。
该单元可以简单如下:
# /etc/systemd/system/media-pi-MyBook.mount
[Mount]
What=/dev/sda1
Where=/media/pi/MyBook
然后,不要将其放在您的覆盖中:
# /etc/systemd/system/[email protected]/override.conf
[Service]
ExecStartPre=/usr/local/bin/mount-sync-drive.sh
执行此操作可确保在运行服务之前挂载可用并正在运行。
# /etc/systemd/system/[email protected]/override.conf
[Unit]
Requires=media-pi-MyBook.mount
After=media-pi-MyBook.mount
现在您可以删除自定义脚本。
这可以解决几个问题,例如能够控制何时卸载单元,以及确保模板的每个实例都存在安装,而无需任何额外的检查。
要卸载,只需简单地操作,它就会自动停止sudo systemctl stop media-pi-MyBook.mount
任何服务。Requires=
这是编写脚本更加困难的事情,尤其是当您有大量模板实例时。
一个额外的细节:
我推荐的覆盖是 in[email protected]/
而不是[email protected]/
.这意味着模板的每个实例都将存在依赖性,syncthing@
而不仅仅是syncthing@admin
.
答案2
从状态检查开始:
systemctl show [email protected] | grep -E 'ProtectSystem|NoNewPrivileges'
您很可能已NoNewPrivileges
启用。这样做的结果是你的进程不被允许成为 root,因此sudo
无法运行。
如果是这种情况,您需要禁用该设置。请参阅我的回答rsyncd service ProtectSystem=off 无效,它相似但不重复,以获取如何更改这些值的完整说明
答案3
sudo
不适用于脚本调用。其目的是验证交互式用户。
您应该尝试重新编写脚本以避免sudo
.您的脚本仅适用sudo
于一行,但其他行不会做太多事情,因此将root
权限扩展到这一行也不是不合理的。
man systemd.service
描述“特殊可执行前缀”。您可以使用这些前缀来ExecStartPre=
更改行为。您对+
以完全权限运行脚本特别感兴趣。
在您的插件中,只需将其添加+
到脚本路径之前即可:
[Service]
ExecStartPre=+/usr/local/bin/mount-sync-drive.sh
然后您可以sudo
从脚本中删除:
#!/bin/bash
exec &>> /var/log/syncthing.log
echo ""
date
# Check if /dev/sda1 is already mounted
if ! grep -qs '/dev/sda1' /proc/mounts; then
# Mount /dev/sda1 to /media/pi/MyBook
echo "Mounting /dev/sda1 to /media/pi/MyBook"
mount -v /dev/sda1 /media/pi/MyBook
fi
额外加分:您在这里进行了大量登录。请注意,mount
已经将它所做的事情打印到标准输出,因此您的 echo 命令有点多余。您还回显换行符和日期。默认情况下,您的设备会自动将脚本的所有标准输出和日期记录到日志中。因此,如果您选择使用日志,yopu 可以删除这些内容以简化脚本。
#!/bin/bash
if ! grep -qs '/dev/sda1' /proc/mounts; then
mount -v /dev/sda1 /media/pi/MyBook
fi
然后您可以使用以下命令检查输出:
$ sudo journalctl -u syncthing*
Feb 21 17:23:14 RPI systemd[1]: Started [email protected] - Syncthing - Open Source Continuous File Synchronization for admin
Feb 21 17:23:14 RPI mount-sync-drive.sh[1234]: mount: /dev/sda1 mounted on /media/pi.