进一步阅读

进一步阅读

我编写了一个脚本,用于侦听来自 FIFO 的命令并收集几个文件以便在我的树莓派上进行调试,所有这些工作正常直到我决定为其编写一个 systemd 单元文件。 runningsystemctl start crashcollector将启动脚本,但它永远不会从正在运行的管道中读取任何内容,但不会执行任何操作,systemctl stop crashcollector需要永远停止服务,所以我猜测我的单元文件出了问题,即使我编写了许多工作正常的文件。

bash脚本:

#!/bin/bash

collectCrashReport() {
    # teleport to cache dir
    cd /mnt/cache
    # remove any previous report
    rm -rf crash/crashreport_*
    # create report directory
    directory=crashreport_`cat /etc/hostname`_$(date +%Y%m%d%H%M%S)
    mkdir $directory
    cd $directory
    # snatch all the logs
    cp -r /var/log/ .
    ps --no-headers -ax > processes.dump
    # dump dmesg to file 
    dmesg > dmesg.dump
    # create crash dir
    mkdir crash
    # zip the whole thing
    zip -qr /mnt/cache/crash/"$directory.zip" .
    # remove collection dir
    rm -rf /mnt/cache/crashreport_*
    # done and done
}

# check if already running and kill
PIDFILE=/var/run/crashcollector.pid
# check if already running
if [ -f $PIDFILE ]; then
    kill `cat $PIDFILE`
fi
echo $$ > $PIDFILE

cleanup() {
    rm -f $PIDFILE
    exit 0
}
# trap them signals 
trap "cleanup" INT TERM EXIT

that_awesome_pipe="CCPipe"
[ -p $that_awesome_pipe ] || mkfifo $that_awesome_pipe
chmod 766 $that_awesome_pipe
while :; do
    if read line; then
        case $line in
        "collect")
            collectCrashReport
            ;;
        *)
            log "Received bad command $line, ignoring..."
            ;;
        esac    
    fi
done <"$that_awesome_pipe"

Systemd单元文件:

[Unit]
Description=Crash report collector
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/crashCollector
ExecStop=/usr/bin/kill -9 `cat /var/run/crashcollector.pid`
KillMode=process
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

不确定我在这里到底缺少什么,删除该if read line块使一切正常工作。

答案1

那里有很多事情不对劲。

  • 不要将ExecStartExecStop视为 shell 命令行。他们不是。 systemd 手册确实警告了这一点。命令替换等 Shell 扩展是不是在这些服务单元文件设置中可用。这是不是shell语言。
  • 当您开始的地方有实际的服务管理器时,不要创建 PID 文件机制。 PID 文件是一种自 20 世纪 80 年代以来就被破坏的机制,正确的服务管理完全消除了这种需要。你有一个服务经理。 将确保任何时候最多只有一个服务实例运行。 将跟踪进程 ID。 当服务关闭时,将处理向服务进程发送终止信号。
  • 不要将基本的服务器端内容放入服务器进程中,例如创建 FIFO 并打开其服务器端。

这样做:

  • 创建一个套接字单元与服务单元并排。
  • 将 FIFO 的所有显式处理从crashCollector.
  • 用于ListenFIFO插座单元。这当然需要绝对路径名。
  • StandardInput=socket在服务单位使用。
  • 让您的crashcollector脚本仅从其标准输入读取。
  • 将所有 PID 文件从crashCollector.
  • 把所有的信号捕获和cleanup()东西从crashCollector.
  • 将所有使用 的显式杀戮ExecStop以及您尝试使用 执行的后续操作KillMode从服务单元中取出。
  • StandardError=journal在服务单位使用。
  • 替换log为简单echo 1>&2到标准错误。

进一步阅读

答案2

我将 fifo 移动到 后,一切都修复了/tmp;不确定会发生什么变化,但现在一切进展顺利。

相关内容