Linux nice 命令

nice 命令用于以指定的优先级运行程序,通过调整进程的nice值来影响CPU调度优先级
注意:nice值的范围是-20到19,数值越低优先级越高。普通用户只能降低优先级(增加nice值),只有root用户可以提高优先级(设置负的nice值)

语法格式

nice [选项] [命令 [参数...]]

常用选项

选项 说明
-n 数值 指定nice值(优先级)
--help 显示帮助信息
--version 显示版本信息

nice值说明

nice值 优先级 说明 谁可以设置
-20 最高 实时优先级 仅root
-10 系统关键进程 仅root
0 普通 默认优先级 所有用户
10 后台任务 所有用户
19 最低 空闲时运行 所有用户

命令示例

示例1:以较低的优先级运行程序

普通用户可以降低进程优先级,避免影响系统性能:

# 以较低的优先级(nice=10)运行压缩任务
nice -n 10 tar -czf backup.tar.gz /home/user/documents/

# 不指定nice值,默认为10
nice tar -czf backup.tar.gz /home/user/documents/
注意:如果不指定-n选项,nice命令默认将nice值增加10
示例2:以较高的优先级运行程序(需要root)

只有root用户可以设置负的nice值,提高进程优先级:

# 以高优先级运行重要服务
sudo nice -n -10 /usr/sbin/nginx

# 以最高优先级运行关键进程
sudo nice -n -20 /usr/sbin/mysqld
警告:设置过高的优先级可能导致系统响应变慢,应谨慎使用
示例3:查看进程的nice值

使用ps命令查看进程的nice值:

# 显示进程的nice值(NI列)
ps -l

# 查看所有进程的nice值
ps -eo pid,ni,cmd

# 查看特定进程的nice值
ps -p $(pidof nginx) -o pid,ni,cmd

# 使用top命令查看(按R键可以调整优先级)
top

ps命令输出中的NI列就是nice值:

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000  1234  1233  0  80   0 -  1234 wait   pts/0    00:00:00 bash
0 R  1000  5678  1234  0  80  10 -  2345 -      pts/0    00:00:00 tar
示例4:结合nohup后台运行

将低优先级的任务放到后台运行:

# 以后台方式运行低优先级任务
nohup nice -n 15 ./long_running_script.sh > output.log 2>&1 &

# 检查后台任务的nice值
ps -p $! -o pid,ni,cmd

或者使用shell脚本控制:

#!/bin/bash
# 后台运行多个低优先级任务
for i in {1..5}; do
    nice -n 15 ./task_${i}.sh > task_${i}.log 2>&1 &
done

# 等待所有后台任务完成
wait
echo "所有任务完成"
示例5:renice命令调整已运行进程的优先级

使用renice命令调整已运行进程的nice值:

# 将进程1234的nice值设为10
renice 10 1234

# 将进程1234的nice值设为-5(需要root)
sudo renice -5 1234

# 调整用户所有进程的优先级
renice 10 -u username

# 调整进程组所有进程的优先级
renice 5 -p 1234 5678  # 多个PID
注意:renice命令用于调整已运行进程的优先级,而nice命令用于启动新进程时设置优先级

实际应用场景

场景1:服务器资源管理

在服务器上合理分配CPU资源:

#!/bin/bash
# 服务器资源管理脚本

# 定义不同服务的优先级
declare -A service_priority=(
    ["nginx"]="-5"
    ["mysql"]="-10"
    ["php-fpm"]="0"
    ["backup"]="15"
    ["cron"]="5"
)

# 调整正在运行服务的优先级
for service in "${!service_priority[@]}"; do
    pids=$(pidof "$service")
    priority="${service_priority[$service]}"

    if [ -n "$pids" ]; then
        for pid in $pids; do
            echo "调整 $service (PID: $pid) 优先级为 $priority"
            sudo renice "$priority" "$pid"
        done
    fi
done

# 启动新的低优先级备份任务
echo "开始低优先级备份..."
nice -n 15 tar -czf /backup/$(date +%Y%m%d).tar.gz /var/www/html/
场景2:桌面系统响应优化

在桌面系统中确保交互式应用的响应速度:

#!/bin/bash
# 桌面系统优化脚本

# 提高GUI进程的优先级
sudo renice -5 $(pidof Xorg)
sudo renice -5 $(pidof gnome-shell)

# 降低后台更新进程的优先级
renice 15 $(pidof unattended-upgr)

# 运行大型编译任务时使用低优先级
nice -n 19 make -j$(nproc)

# 监控系统响应
echo "当前高优先级进程:"
ps -eo pid,ni,cmd | awk '$2 < 0 {print $0}' | head -10
场景3:批处理任务调度

批量处理大量数据时避免影响系统:

#!/bin/bash
# 批处理任务调度器

# 设置批处理任务的优先级
BATCH_NICE=15
MAX_JOBS=4

# 批处理任务列表
tasks=(
    "process_data.py --input=data1.csv"
    "process_data.py --input=data2.csv"
    "process_data.py --input=data3.csv"
    "process_data.py --input=data4.csv"
    "process_data.py --input=data5.csv"
)

# 使用低优先级运行批处理任务
job_count=0
for task in "${tasks[@]}"; do
    # 如果达到最大并发数,等待
    while [ $(jobs -r | wc -l) -ge $MAX_JOBS ]; do
        sleep 1
    done

    # 启动低优先级任务
    nice -n $BATCH_NICE $task > /dev/null 2>&1 &
    echo "启动任务: $task (PID: $!)"
    ((job_count++))
done

echo "共启动 $job_count 个低优先级批处理任务"
wait
echo "所有批处理任务完成"

nice与renice对比

命令 用途 操作时机 权限要求 示例
nice 启动时设置优先级 进程启动前 普通用户只能提高nice值 nice -n 10 command
renice 调整运行中进程的优先级 进程运行中 普通用户只能提高nice值 renice 10 1234
ionice 调整I/O优先级 启动前或运行中 普通用户有限制 ionice -c3 command
chrt 设置实时调度策略 启动前或运行中 需要root权限 chrt -f 99 command

常见问题解答

nice值通过以下方式影响进程调度:

  1. 调度优先级:Linux调度器使用nice值计算进程的动态优先级
  2. CPU时间分配:低nice值(高优先级)的进程获得更多的CPU时间片
  3. 响应速度:高优先级进程在就绪队列中排队时间更短
  4. 抢占性:高优先级进程可以抢占低优先级进程的CPU时间

计算公式:

动态优先级 = 静态优先级(120) + nice值

其中静态优先级通常是120,所以:

  • nice=-20 → 动态优先级=100(最高)
  • nice=0 → 动态优先级=120(默认)
  • nice=19 → 动态优先级=139(最低)

注意:这只是CFS调度器的一种实现,实际调度还受其他因素影响。

这是Linux系统的安全特性:

  1. 防止拒绝服务:如果普通用户可以将进程设为最高优先级,可能占用所有CPU资源,导致系统无响应
  2. 保护系统进程:确保系统关键进程(如init、内核线程)始终有足够的CPU时间
  3. 公平性:防止一个用户独占系统资源,影响其他用户的体验

示例:

# 普通用户尝试设置负nice值
$ nice -n -10 sleep 100
nice: cannot set niceness: Permission denied

# 普通用户只能提高nice值
$ nice -n 10 sleep 100  # 成功
$ nice sleep 100        # 默认nice=10,成功

绕过限制的方法(不推荐):

# 1. 使用sudo(需要管理员授权)
sudo nice -n -10 command

# 2. 配置sudoers允许特定用户设置负nice值
# 在/etc/sudoers中添加:
# username ALL=(ALL) NOPASSWD: /usr/bin/nice -n -[0-9]* *

# 3. 使用capabilities(高级)
sudo setcap 'cap_sys_nice=ep' /path/to/program

nice命令:

  • 调整CPU调度优先级
  • 影响进程获得CPU时间的能力
  • nice值范围:-20到19
  • 适用于CPU密集型任务

ionice命令:

  • 调整I/O调度优先级
  • 影响进程执行磁盘I/O操作的能力
  • 调度类:0(无限制)、1(实时)、2(尽力)、3(空闲)
  • 适用于I/O密集型任务

示例对比:

# 同时调整CPU和I/O优先级
nice -n 10 ionice -c3 ./data_processing.sh

# 查看进程的CPU和I/O优先级
ps -eo pid,ni,cmd | grep data_processing
ionice -p $(pidof data_processing.sh)

使用场景:

  • 数据库服务器:需要高CPU和I/O优先级
  • 备份任务:低CPU和I/O优先级,避免影响生产服务
  • 视频编码:高CPU优先级,普通I/O优先级
  • 日志分析:低CPU优先级,高I/O优先级

有几种方法可以永久设置进程的优先级:

方法1:在启动脚本中使用nice

#!/bin/bash
# /etc/init.d/myservice
# 在启动命令前添加nice
nice -n -5 /usr/sbin/myservice

方法2:使用systemd服务单元

# /etc/systemd/system/myservice.service
[Service]
ExecStart=/usr/bin/nice -n -10 /usr/sbin/myservice
Nice=-10
IOSchedulingClass=realtime
IOSchedulingPriority=0

方法3:使用start-stop-daemon(Debian系)

start-stop-daemon --start --quiet --pidfile /var/run/myservice.pid \
    --nicelevel -10 --exec /usr/sbin/myservice

方法4:在crontab中设置

# /etc/crontab
# 指定用户运行低优先级备份任务
0 2 * * * root nice -n 15 /usr/local/bin/backup.sh

方法5:修改程序的默认nice值

# 使用setcap给程序设置能力
sudo setcap 'cap_sys_nice=ep' /usr/bin/mytask
# 然后在程序中调用setpriority()系统调用

验证设置:

# 重启服务后检查优先级
systemctl restart myservice
ps -p $(pidof myservice) -o pid,ni,cmd

最佳实践

  1. 合理设置优先级:系统关键进程使用高优先级,后台任务使用低优先级
  2. 避免过度调整:不要将所有进程都设为高优先级,否则等于没有优先级
  3. 监控优先级:定期检查进程优先级,确保符合预期
  4. 结合I/O优先级:对于I/O密集型任务,同时使用ionice调整I/O优先级
  5. 记录调整:在生产环境中记录所有优先级调整,便于故障排查
  6. 测试验证:在调整优先级前,在测试环境中验证效果
  7. 使用脚本管理:对于复杂的优先级设置,使用脚本统一管理
  8. 遵循最小权限:只给必要的进程高优先级,普通进程使用默认或低优先级
#!/bin/bash
# 系统优先级管理脚本

# 定义优先级策略
declare -A priority_policy=(
    # 进程名:优先级:说明
    ["sshd"]="0:安全外壳服务"
    ["nginx"]="-5:Web服务器"
    ["mysql"]="-10:数据库服务"
    ["backup"]="19:备份任务"
    ["batch-job"]="15:批处理任务"
)

# 应用优先级策略
apply_priority_policy() {
    echo "应用优先级策略..."

    for process in "${!priority_policy[@]}"; do
        IFS=':' read -r priority description <<< "${priority_policy[$process]}"
        pids=$(pidof "$process")

        if [ -n "$pids" ]; then
            for pid in $pids; do
                current_nice=$(ps -p "$pid" -o ni= | tr -d ' ')
                if [ "$current_nice" != "$priority" ]; then
                    echo "调整 $process (PID:$pid) $description nice: $current_nice -> $priority"
                    sudo renice "$priority" "$pid"
                fi
            done
        fi
    done
}

# 检查优先级冲突
check_priority_conflicts() {
    echo "检查优先级冲突..."

    # 检查是否有过多高优先级进程
    high_priority_count=$(ps -eo ni | grep -c "^-")
    if [ "$high_priority_count" -gt 10 ]; then
        echo "警告:发现 $high_priority_count 个高优先级进程"
        ps -eo pid,ni,cmd | grep "^-"
    fi

    # 检查系统负载与优先级分布
    load_average=$(uptime | awk -F'load average:' '{print $2}')
    echo "系统负载: $load_average"
}

# 主程序
apply_priority_policy
check_priority_conflicts