#!/usr/bin/env bash # startb: start a command in the background with journald or file logging fallback. # Usage: # startb [--log logfile] COMMAND [ARGS...] # Environment: # STARTB_LOGFILE=... to force a log file. set -euo pipefail # PATH may be incomplete from systemd login env; restore from interactive shell. PATH=$(zsh -c -i 'echo $PATH') export PATH SCRIPT_NAME="${0##*/}" usage() { cat <&2 usage fi LOG_FILE=$1 shift fi if [ $# -lt 1 ]; then usage fi COMMAND=("$@") UNIT_BASE=$(basename "${COMMAND[0]}") UNIT_BASE=${UNIT_BASE:-cmd} UNIT_NAME="${UNIT_BASE}-$(date +%Y%m%d_%H%M%S_%N)" log_to_file() { local path=$1 mkdir -p "$(dirname "$path")" 2>/dev/null || true touch "$path" || { echo "Failed to touch logfile: $path" >&2 return 1 } nohup setsid "${COMMAND[@]}" >>"$path" 2>&1 & local pid=$! disown "$pid" 2>/dev/null || true echo "$UNIT_NAME started in background (pid=$pid), logs: $path" return 0 } log_to_journal() { # 不按雪叶那样写基本记录不到输出,懒得调了,直接屏蔽。 # if command -v systemd-run >/dev/null 2>&1; then # systemd-run --user --scope --unit="$UNIT_NAME" -- "${COMMAND[@]}" >/dev/null 2>&1 & # local pid=$! # echo "$UNIT_NAME started in systemd scope (pid=$pid), journald logging enabled" # return 0 # fi if command -v systemd-cat >/dev/null 2>&1; then nohup setsid systemd-cat -t "$UNIT_BASE" -- "${COMMAND[@]}" >/dev/null 2>&1 & local pid=$! disown "$pid" 2>/dev/null || true echo "$UNIT_BASE started with systemd-cat (pid=$pid), journald logging enabled" return 0 fi return 1 } if [ -n "$LOG_FILE" ]; then log_to_file "$LOG_FILE" || exit 1 exit 0 fi if log_to_journal; then exit 0 fi # Fallback log path when journald is unavailable. LOG_FILE="/tmp/${USER:-unknown}/startb/${UNIT_NAME}.log" log_to_file "$LOG_FILE"