我有bash脚本,应该执行,当特定的设备连接。当我从终端启动它时,我没有得到任何问题,但是,当我启动它作为systemd服务时,我得到了管道破裂错误。
мая 07 10:47:49 nixos systemd[1563]: Starting garmin.service...
мая 07 10:47:51 nixos bash[6951]: grep: ошибка записи: Broken pipe
мая 07 10:47:51 nixos systemd[1563]: garmin.service: Control process exited, code=exited, status=127/n/a
мая 07 10:47:51 nixos systemd[1563]: garmin.service: Failed with result 'exit-code'.
мая 07 10:47:51 nixos systemd[1563]: Failed to start garmin.service.
这是我的systemd服务:
[Unit]
After=run-media-serg-GARMIN.mount
Requires=run-media-serg-GARMIN.mount
[Service]
Environment="LOCALE_ARCHIVE=/nix/store/ckkhm153z75sw6z5nr277kvn2pi4z8jy-glibc-locales-2.35-224/lib/locale/locale-archive"
Environment="PATH=/nix/store/l6jgwxkc3jhr029vfzfwzcy28iyckwsj-coreutils-9.1/bin:/nix/store/gn1s1s5z19cf0wiir2cd38jckcjc6kn6-findutils-4.9.0/bin:/nix/store/pvb117r7fhwb08717ks21a6y9hlnp63b-gnugrep-3.7/bin:/nix/store/v0hg83sdv4v51c0prmdigry6wdmmpzmp-gnused-4.8/bin:/nix/store/34am2kh69ll6q03731imxf21jdbizda2-systemd-251.15/bin:/nix/store/l6jgwxkc3jhr029vfzfwzcy28iyckwsj-coreutils-9.1/sbin:/nix/store/gn1s1s5z19cf0wiir2cd38jckcjc6kn6-findutils-4.9.0/sbin:/nix/store/pvb117r7fhwb08717ks21a6y9hlnp63b-gnugrep-3.7/sbin:/nix/store/v0hg83sdv4v51c0prmdigry6wdmmpzmp-gnused-4.8/sbin:/nix/store/34am2kh69ll6q03731imxf21jdbizda2-systemd-251.15/sbin"
Environment="TZDIR=/nix/store/z0kg1c0f8fx6r4rgg5bdy01lb2b9izqg-tzdata-2023a/share/zoneinfo"
ExecStart=/nix/store/kga2r02rmyxl14sg96nxbdhifq3rb8lc-bash-5.1-p16/bin/bash -c /nix/store/jqfh2bnzag50wlghwnw52mq2nzr8bzz2-garmin-backup/bin/garmin-backup
Type=forking
这是我的剧本:
简而言之,它会检查是否安装了正确的设备,然后用rsync同步一些文件夹,并发送通知和写日志。
#!/usr/bin/env bash
backupDir="/home/serg/Backup/Garmin Edge 830/"
#I need to export this variables for notify-send
export DISPLAY=:0
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
on_error()
{
_MSG_=$1
echo "$_MSG_"
exit 1
}
check_mount()
{
_MOUNT_=$1
_MSG_=$2
if [ ! -d "$_MOUNT_" ]; then
echo "Path to $_MSG_ mount point is not exists"
exit 1
fi
}
writeLog()
{
_LOG_=$1
_SAVE_PATH_=$2
local outputPath="$_SAVE_PATH_/backup_history_${_LOG_}".log
if [ ! -e "$outputPath" ]; then
echo "Backup_log: " > "$outputPath"
fi
date >> "$outputPath"
}
garmin()
{
mpointGarmin="$(df -h | grep -i "Garmin" | awk '{print $NF}')"
check_mount "${mpointGarmin}" "Garmin"
inputDir="${mpointGarmin}/Garmin/"
copyArray=(
"Activities"
"Locations"
"Records"
"Settings"
"Sports"
"Totals"
"Weight"
)
#https://stackoverflow.com/questions/9952000/using-rsync-include-and-exclude-options-to-include-directory-and-file-by-pattern
#https://github.com/JonnyTischbein/rsync-server/blob/master/sync-folder.sh
#Glob should be used inside array (according shellcheck)
#See https://www.shellcheck.net/wiki/SC2125
for val in "${copyArray[@]}"
do
copyStr+=( --include="$val"/*** )
done
#LOG_NAME="_garmin"
rsync --dry-run --no-perms --checksum --progress -v -r "${copyStr[@]}" \
--exclude=* "${inputDir}" "${backupDir}"
RET_CODE=$?
if test $RET_CODE -eq 0; then
#writeLog "$LOG_NAME" "${backupDir}"
notify-send "Garmin 830 Backup is Done"
fi
}
garmin
我发现了一条导致这个问题的线。这是
mpointGarmin="$(df -h | grep -i "Garmin" | awk '{print $NF}')"
当我删除这个管道和子shell和硬代码挂载点它的工作。
据我所知,systemd不喜欢subshell调用管道?还是我错了?我该怎么补救?
1条答案
按热度按时间mjqavswn1#
从技术上讲,当管道的“读取器”(右侧)已经退出,但“写入器”(左侧)仍在尝试写入更多数据时,“中断管道”是一种正常的情况。
通常在这种情况下,内核会在编写器收到“Broken pipe”错误代码之前使用SIGPIPE * 自动杀死编写器。然而,systemd默认设置信号处理程序为 * 忽略 * SIGPIPE,以避免潜在的(模糊的)安全问题(服务被欺骗写入封闭管道)。
当shell脚本作为服务运行时,指定
[Service] IgnoreSIGPIPE=no
以将SIGPIPE行为返回为默认值(即使其立即终止进程)。