Linux命令-nohup(使进程忽略挂起(HUP)信号并在后台继续运行)

nohup 是 Linux 中用于使进程忽略挂起(HUP)信号并在后台继续运行的命令。它通常用于在用户注销后仍需要继续运行的长时间任务。

📦 基本语法

bash 复制代码
nohup 命令 [参数]...
nohup 命令 [参数]... > 输出文件

🎯 主要特性

  1. 忽略挂起信号:当终端关闭时,进程不会收到 SIGHUP 信号而终止
  2. 输出重定向 :默认将输出重定向到 nohup.out 文件
  3. 后台运行 :常与 & 结合使用,让进程在后台运行
  4. 脱离终端:进程与当前终端分离,不受终端关闭影响

💡 核心用法示例

1. 基本用法

bash 复制代码
# 启动进程并忽略挂起信号
nohup 命令

# 启动进程并在后台运行
nohup 命令 &

# 指定输出文件
nohup 命令 > output.log

# 后台运行并指定输出文件
nohup 命令 > output.log 2>&1 &

# 将标准输出和错误输出都重定向
nohup 命令 > output.log 2>&1

2. 常见使用场景

bash 复制代码
# 1. 运行长时间脚本
nohup ./long_running_script.sh &

# 2. 启动服务器应用
nohup java -jar myapp.jar > app.log 2>&1 &

# 3. 数据库备份
nohup mysqldump -u root -p database > backup.sql &

# 4. 大文件处理
nohup gzip -c largefile.dat > largefile.dat.gz &

# 5. 编译项目
nohup make -j4 > compile.log 2>&1 &

# 6. 下载大文件
nohup wget -c http://example.com/large.iso &

# 7. 科学计算
nohup python compute.py > result.log 2>&1 &

3. 输出重定向控制

bash 复制代码
# 只重定向标准输出
nohup command > output.log

# 重定向标准输出和错误输出到不同文件
nohup command > output.log 2> error.log

# 重定向标准输出和错误输出到同一文件
nohup command > output.log 2>&1

# 丢弃所有输出
nohup command > /dev/null 2>&1

# 只保留错误输出
nohup command > /dev/null 2> error.log

🔧 实用技巧

1. 查看和管理 nohup 进程

bash 复制代码
# 查找所有 nohup 启动的进程
ps aux | grep nohup
ps aux | grep -v grep | grep nohup

# 查找特定用户的 nohup 进程
ps -u username -o pid,cmd | grep nohup

# 查看进程树
pstree -p $(pgrep -f "nohup.*command")

# 查看 nohup 输出文件
tail -f nohup.out
tail -f output.log

2. 停止 nohup 进程

bash 复制代码
# 找到进程ID
ps aux | grep "command_name"

# 发送终止信号
kill PID
kill -9 PID  # 强制终止

# 停止所有相关进程
pkill -f "command_name"
kill $(pgrep -f "command_name")

3. 结合其他命令使用

bash 复制代码
# 使用 time 计时
nohup time ./script.sh > output.log 2>&1 &

# 结合 nice 设置优先级
nohup nice -n 10 ./script.sh > output.log 2>&1 &

# 结合 setsid 完全脱离终端
nohup setsid ./daemon.sh > /dev/null 2>&1 &

# 在 screen/tmux 中使用
# 先在 screen/tmux 中启动
nohup ./script.sh > output.log 2>&1
# 然后 detach,可以随时 reattach

📊 输出文件管理

1. 自动管理输出文件

bash 复制代码
#!/bin/bash
# 自动管理 nohup 输出文件

LOG_DIR="/var/log/nohup_logs"
LOG_FILE="${LOG_DIR}/task_$(date +%Y%m%d_%H%M%S).log"

# 创建日志目录
mkdir -p "$LOG_DIR"

# 启动任务
nohup ./long_task.sh > "$LOG_FILE" 2>&1 &

echo "任务已启动,日志文件: $LOG_FILE"
echo "PID: $!"

2. 日志轮转脚本

bash 复制代码
#!/bin/bash
# nohup 日志轮转脚本

LOG_DIR="/var/log/nohup_logs"
RETENTION_DAYS=7
MAX_LOG_SIZE=100M  # 100MB

# 清理旧日志
find "$LOG_DIR" -name "*.log" -mtime +$RETENTION_DAYS -delete

# 检查并分割大日志文件
for logfile in "$LOG_DIR"/*.log; do
    if [[ -f "$logfile" ]]; then
        size=$(stat -c%s "$logfile" 2>/dev/null || stat -f%z "$logfile" 2>/dev/null)
        if [[ $size -gt 104857600 ]]; then  # 100MB in bytes
            mv "$logfile" "${logfile}.$(date +%Y%m%d_%H%M%S)"
            touch "$logfile"
        fi
    fi
done

⚡ 高级用法

1. 监控和重启脚本

bash 复制代码
#!/bin/bash
# 监控和自动重启脚本

APP_NAME="myapp"
APP_CMD="java -jar myapp.jar"
LOG_FILE="/var/log/${APP_NAME}.log"
PID_FILE="/var/run/${APP_NAME}.pid"
CHECK_INTERVAL=60

# 启动应用
start_app() {
    echo "启动 $APP_NAME..."
    nohup $APP_CMD > "$LOG_FILE" 2>&1 &
    echo $! > "$PID_FILE"
    echo "PID: $(cat $PID_FILE)"
}

# 停止应用
stop_app() {
    if [[ -f "$PID_FILE" ]]; then
        PID=$(cat "$PID_FILE")
        if kill -0 $PID 2>/dev/null; then
            echo "停止 $APP_NAME (PID: $PID)..."
            kill $PID
            sleep 5
            if kill -0 $PID 2>/dev/null; then
                echo "强制停止..."
                kill -9 $PID
            fi
        fi
        rm -f "$PID_FILE"
    fi
}

# 检查应用状态
check_app() {
    if [[ -f "$PID_FILE" ]]; then
        PID=$(cat "$PID_FILE")
        if ! kill -0 $PID 2>/dev/null; then
            echo "应用已停止,重新启动..."
            start_app
        fi
    else
        echo "PID文件不存在,启动应用..."
        start_app
    fi
}

# 主循环
trap 'stop_app; exit 0' INT TERM
echo "开始监控 $APP_NAME..."

while true; do
    check_app
    sleep "$CHECK_INTERVAL"
done

2. 批量启动任务

bash 复制代码
#!/bin/bash
# 批量启动 nohup 任务

declare -A TASKS=(
    ["task1"]="./task1.sh"
    ["task2"]="./task2.sh"
    ["task3"]="python3 task3.py"
    ["task4"]="node task4.js"
)

LOG_DIR="logs"
mkdir -p "$LOG_DIR"

echo "开始批量启动任务..."
echo "======================"

for task_name in "${!TASKS[@]}"; do
    cmd="${TASKS[$task_name]}"
    log_file="$LOG_DIR/${task_name}_$(date +%Y%m%d_%H%M%S).log"
    
    echo "启动: $task_name"
    echo "命令: $cmd"
    echo "日志: $log_file"
    
    nohup $cmd > "$log_file" 2>&1 &
    pid=$!
    
    echo "PID: $pid"
    echo "$pid" > "$LOG_DIR/${task_name}.pid"
    echo "---"
done

echo "所有任务已启动"
echo "查看进程: ps aux | grep -E '$(echo ${TASKS[@]} | tr ' ' '|')'"

🔍 常见问题排查

1. 检查 nohup 是否正常工作

bash 复制代码
# 测试脚本
cat > test_nohup.sh << 'EOF'
#!/bin/bash
for i in {1..10}; do
    echo "Count: $i at $(date)"
    sleep 1
done
EOF

chmod +x test_nohup.sh

# 启动测试
nohup ./test_nohup.sh > test.log 2>&1 &
echo "PID: $!"

# 立即退出终端,重新登录后检查
cat test.log

2. 查看进程状态

bash 复制代码
# 查看进程是否仍在运行
ps -p $PID -o pid,cmd,state

# 查看进程打开的文件
lsof -p $PID

# 查看进程资源使用
top -p $PID

⚠️ 重要注意事项

  1. 输出重定向:如果不重定向输出,可能会占用磁盘空间
  2. 权限问题:某些操作可能需要特定权限
  3. 信号处理:nohup 只忽略 SIGHUP,其他信号仍需处理
  4. 资源限制:长期运行的进程可能消耗系统资源
  5. 日志管理:定期清理 nohup.out 文件
  6. 环境变量:nohup 会继承当前 shell 的环境变量

🔄 替代方案

工具 说明 适用场景
screen 终端复用器,会话可分离 需要交互的长时间任务
tmux 现代终端复用器 复杂的多任务管理
disown 从 shell 作业表中移除作业 已启动的作业需要后台运行
setsid 在新会话中运行程序 完全脱离终端的守护进程
systemd 系统和服务管理器 系统服务管理

🎯 最佳实践

  1. 始终重定向输出:避免 nohup.out 文件无限增长
  2. 使用日志轮转:定期清理和分割日志文件
  3. 记录进程ID:方便后续管理
  4. 设置资源限制:使用 ulimit 避免资源耗尽
  5. 监控进程状态:定期检查进程是否正常运行
  6. 优雅停止:为进程实现信号处理,支持优雅关闭

nohup 是 Linux 系统管理中非常实用的工具,特别适合运行不需要用户交互的长时间任务。结合适当的重定向和监控,可以确保任务稳定可靠地运行。

相关推荐
kebidaixu1 小时前
板级设备树驱动修改实战:从PWM到CAN,释放GPIO的完整指南
linux
爱喝水的鱼丶1 小时前
SAP-ABAP:SAP 简单报表输出开发系列(共6篇)第三篇:SAP ALV 报表样式定制:字段布局与交互功能配置
服务器·开发语言·学习·交互·sap·abap
一码当前1 小时前
【全志】 OKT153(sun8iw22) 启动链全流程详解
linux
STDD1 小时前
VictoriaLogs:轻量级日志存储方案,Loki 的高效替代
运维·jenkins
键盘上的猫头鹰1 小时前
【Linux 基础教程(一)】概述、安装与网络配置:VMware + CentOS + NAT + XShell 远程连接
linux·网络·centos
枳实-叶1 小时前
【Linux驱动开发】第18天:I2C驱动深度解析
linux·运维·驱动开发
shandianchengzi1 小时前
【记录】Ubuntu|Ubuntu 26.04 笔记本耗电过快,排查 省电过程
linux·运维·ubuntu
一叶星殇2 小时前
日志成海,何以检索:Serilog 解锁 .NET 日志可查询新范式
运维·服务器
企服AI产品测评局2 小时前
AI Agent实测:Agent Store现成应用如何重塑企业自动化?
运维·人工智能·ai·chatgpt·自动化