xiaohongshu
xiaohongshu
background-service-manager
Create and manage long-running background processes with start/stop/status controls, logging, and monitoring. Use for batch processing jobs, data pipelines, continuous services, or any long-running tasks.
Full skill instructions
This skill creates service management scripts for long-running background processes. Includes start/stop controls, PID management, log rotation, status monitoring, and graceful shutdown handling.
SERVICE_CMD to your processchmod +x service.sh./service.sh start./service.sh status or ./service.sh logs#!/bin/bash
# Quick service wrapper
SERVICE_NAME="myservice"
PID_FILE="/tmp/${SERVICE_NAME}.pid"
LOG_FILE="/tmp/${SERVICE_NAME}.log"
SERVICE_CMD="python3 ./worker.py"
case "$1" in
start)
nohup $SERVICE_CMD >> "$LOG_FILE" 2>&1 &
echo $! > "$PID_FILE"
echo "Started (PID: $!)"
;;
stop)
[ -f "$PID_FILE" ] && kill $(cat "$PID_FILE") && rm "$PID_FILE"
;;
status)
[ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null && echo "Running" || echo "Stopped"
;;
*) echo "Usage: $0 {start|stop|status}" ;;
esac
+-------------------------------------------------+
| Service Manager Script |
+-------------------------------------------------+
| start | stop | status | restart |
+-----+-----+----+-----+----+-----+------+-------+
| | | |
v v v v
+----------+ +--------+ +--------+ +--------------+
| PID File | | Kill | | Check | | Stop + Start |
| + nohup | |Process | | PID | | |
+----------+ +--------+ +--------+ +--------------+
|
v
+--------------------------------------+
| Log Files |
| /tmp/service.log /tmp/service.pid |
+--------------------------------------+
#!/bin/bash
# service.sh - Generic service manager
SERVICE_NAME="myservice"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PID_FILE="/tmp/${SERVICE_NAME}.pid"
LOG_FILE="/tmp/${SERVICE_NAME}.log"
# Command to run (customize this)
SERVICE_CMD="python3 ${SCRIPT_DIR}/worker.py"
start() {
if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
echo "Already running (PID: $(cat $PID_FILE))"
return 1
fi
echo "Starting ${SERVICE_NAME}..."
nohup $SERVICE_CMD >> "$LOG_FILE" 2>&1 &
echo $! > "$PID_FILE"
echo "Started (PID: $!)"
}
stop() {
if [ ! -f "$PID_FILE" ]; then
echo "Not running (no PID file)"
return 1
fi
PID=$(cat "$PID_FILE")
if kill -0 "$PID" 2>/dev/null; then
echo "Stopping ${SERVICE_NAME} (PID: $PID)..."
kill "$PID"
# Wait for graceful shutdown
for i in {1..10}; do
if ! kill -0 "$PID" 2>/dev/null; then
break
fi
sleep 1
done
# Force kill if still running
if kill -0 "$PID" 2>/dev/null; then
echo "Force killing..."
kill -9 "$PID"
fi
rm -f "$PID_FILE"
echo "Stopped"
else
echo "Process not running, cleaning up PID file"
rm -f "$PID_FILE"
fi
}
status() {
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if kill -0 "$PID" 2>/dev/null; then
echo "Running (PID: $PID)"
# Show resource usage
ps -p "$PID" -o pid,pcpu,pmem,etime,cmd --no-headers 2>/dev/null
return 0
else
echo "Not running (stale PID file)"
return 1
fi
else
echo "Not running"
return 1
fi
}
restart() {
stop
sleep 2
start
}
logs() {
if [ -f "$LOG_FILE" ]; then
tail -f "$LOG_FILE"
else
echo "No log file found: $LOG_FILE"
fi
}
case "$1" in
start) start ;;
stop) stop ;;
status) status ;;
restart) restart ;;
logs) logs ;;
*)
echo "Usage: $0 {start|stop|status|restart|logs}"
exit 1
;;
esac
#!/bin/bash
# services.sh - Manage multiple services
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Define services
declare -A SERVICES=(
["extract"]="python3 ${SCRIPT_DIR}/extract.py"
["embed"]="python3 ${SCRIPT_DIR}/embed.py"
["api"]="python3 ${SCRIPT_DIR}/api.py"
)
get_pid_file() {
echo "/tmp/${1}.pid"
}
get_log_file() {
echo "/tmp/${1}.log"
}
start_service() {
local name="$1"
local cmd="${SERVICES[$name]}"
local pid_file=$(get_pid_file "$name")
local log_file=$(get_log_file "$name")
if [ -z "$cmd" ]; then
echo "Unknown service: $name"
return 1
fi
if [ -f "$pid_file" ] && kill -0 $(cat "$pid_file") 2>/dev/null; then
echo "$name: Already running"
return 1
fi
echo "Starting $name..."
nohup $cmd >> "$log_file" 2>&1 &
echo $! > "$pid_file"
echo "$name: Started (PID: $!)"
}
stop_service() {
local name="$1"
local pid_file=$(get_pid_file "$name")
if [ ! -f "$pid_file" ]; then
echo "$name: Not running"
return 1
fi
local pid=$(cat "$pid_file")
if kill -0 "$pid" 2>/dev/null; then
kill "$pid"
rm -f "$pid_file"
echo "$name: Stopped"
else
rm -f "$pid_file"
echo "$name: Already stopped (cleaned PID file)"
fi
}
status_all() {
echo "Service Status:"
echo "-------------------------------------"
for name in "${!SERVICES[@]}"; do
local pid_file=$(get_pid_file "$name")
if [ -f "$pid_file" ] && kill -0 $(cat "$pid_file") 2>/dev/null; then
printf " %-12s * Running (PID: %s)\n" "$name" "$(cat $pid_file)"
else
printf " %-12s o Stopped\n" "$name"
fi
done
}
start_all() {
for name in "${!SERVICES[@]}"; do
start_service "$name"
done
}
stop_all() {
for name in "${!SERVICES[@]}"; do
stop_service "$name"
done
}
case "$1" in
start)
if [ -n "$2" ]; then
start_service "$2"
else
start_all
fi
;;
stop)
if [ -n "$2" ]; then
stop_service "$2"
else
stop_all
fi
;;
status) status_all ;;
restart)
stop_all
sleep 2
start_all
;;
*)
echo "Usage: $0 {start|stop|status|restart} [service_name]"
echo ""
echo "Available services:"
for name in "${!SERVICES[@]}"; do
echo " - $name"
done
;;
esac
#!/bin/bash
# status.sh - Rich status display
DB_PATH="${1:-./database.db}"
# Colors
BLUE='\033[0;34m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
BOLD='\033[1m'
CYAN='\033[0;36m'
print_header() {
echo -e "${BLUE}${BOLD}=======================================================${NC}"
echo -e "${BLUE}${BOLD} SERVICE STATUS DASHBOARD${NC}"
echo -e "${BLUE}${BOLD}=======================================================${NC}"
echo ""
}
print_section() {
echo -e "${CYAN}${BOLD}$1${NC}"
}
check_process() {
local name="$1"
local pid_file="/tmp/${name}.pid"
if [ -f "$pid_file" ] && kill -0 $(cat "$pid_file") 2>/dev/null; then
echo -e " ${name}: ${GREEN}*${NC} Running (PID: $(cat $pid_file))"
else
echo -e " ${name}: ${YELLOW}o${NC} Not running"
fi
}
get_db_stats() {
if [ -f "$DB_PATH" ]; then
local total=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM documents" 2>/dev/null || echo "0")
local extracted=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM documents WHERE extracted=1" 2>/dev/null || echo "0")
local chunks=$(sqlite3 "$DB_PATH" "SELECT COUNT(*) FROM chunks" 2>/dev/null || echo "0")
echo -e " Total Documents: ${BOLD}${total}${NC}"
echo -e " Extracted: ${BOLD}${extracted}${NC}"
echo -e " Total Chunks: ${BOLD}${chunks}${NC}"
else
echo -e " ${YELLOW}Database not found${NC}"
fi
}
show_recent_logs() {
local log_file="$1"
local lines="${2:-3}"
if [ -f "$log_file" ]; then
echo " $(tail -1 "$log_file" | cut -c1-60)..."
else
echo " No logs available"
fi
}
# Main display
print_header
echo -e "${CYAN}${BOLD}Database Statistics${NC}"
get_db_stats
echo ""
echo -e "${CYAN}${BOLD}Background Processes${NC}"
check_process "extract"
check_process "embed"
check_process "api"
echo ""
echo -e "${CYAN}${BOLD}Recent Activity${NC}"
echo -n " Last extract: "
show_recent_logs "/tmp/extract.log"
echo -n " Last embed: "
show_recent_logs "/tmp/embed.log"
echo ""
echo -e "${BLUE}=======================================================${NC}"
#!/usr/bin/env python3
"""Python service with graceful shutdown."""
import signal
import sys
import time
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class GracefulShutdown:
"""Handle graceful shutdown on SIGTERM/SIGINT."""
def __init__(self):
self.shutdown_requested = False
signal.signal(signal.SIGTERM, self._handler)
signal.signal(signal.SIGINT, self._handler)
def _handler(self, signum, frame):
logger.info(f"Received signal {signum}, shutting down...")
self.shutdown_requested = True
@property
def should_continue(self):
return not self.shutdown_requested
def main():
shutdown = GracefulShutdown()
logger.info("Service started")
try:
while shutdown.should_continue:
# Your main processing loop
do_work()
# Check for shutdown between iterations
if shutdown.shutdown_requested:
break
time.sleep(1)
except Exception as e:
logger.error(f"Error: {e}")
raise
finally:
cleanup()
logger.info("Service stopped")
def do_work():
"""Main work function - customize this."""
pass
def cleanup():
"""Cleanup on shutdown - customize this."""
pass
if __name__ == '__main__':
main()
Before creating service:
During setup:
After deployment:
Error: "Already running"
Error: "Permission denied"
chmod +x service.sh, check file ownershipError: Process dies immediately
Error: Can't write PID file
Error: Logs not appearing
>> "$LOG_FILE" 2>&1 in nohup command/tmp/ or dedicated log directory| Metric | Target | How to Measure |
|---|---|---|
| Uptime | >99.9% | Time running / total time |
| Restart count | <1/day | Number of restarts needed |
| Memory usage | <80% limit | ps output / allocated |
| CPU usage | <70% average | ps output over time |
| Log size | <100MB/day | Log file growth rate |
| Graceful shutdowns | 100% | Clean stops / total stops |
# Single service
./service.sh start
./service.sh status
./service.sh logs
./service.sh stop
# Multiple services
./services.sh start # Start all
./services.sh start extract # Start specific
./services.sh status # Show all status
./services.sh stop # Stop all
# Status dashboard
./status.sh
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience