nice 命令详解与参数实测(Ubuntu 22.04)

逐项实测 Ubuntu 22.04 的 nice(GNU coreutils 8.32):无参查看当前值、默认 +10、-n/--adjustment 指定调整量、正值夹取上界 19、负值与权限边界(CapEff 排查法)、普通用户只能调高不能调负、PR/NI/S 三列口径对照与老式写法,附低优先级跑批等实战场景与常见问题排查。

Linux命令Linux系统UbuntuUbuntu 22.04命令行进程管理2026/10/15

nice 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 nice 的每一个常用参数与行为——无参查看当前 nice 值、默认 +10 调整、-n/--adjustment 指定调整量、nice 值范围 -20~19 的夹取规则、负值调整的权限边界、普通用户只能调高的限制、PR/NI/S 三列解读、老式写法与 --help/--version,全部命令与回显已在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。

一、环境信息

本篇所有命令与回显均在以下环境实测采集,读者在同等环境(Ubuntu 22.04 服务器、GNU coreutils 8.32)执行应得到一致结果。

  • 操作系统:Ubuntu 22.04.5 LTS(PRETTY_NAME="Ubuntu 22.04.5 LTS")
  • 架构:x86_64
  • nice 版本:GNU coreutils 8.32(nice (GNU coreutils) 8.32)
  • nice 路径:/usr/bin/nice(/bin/nice 为同一文件的兼容链接)
  • 执行身份:root(负值与普通用户限制的对照实验另建了演示用户 niceu1)
  • 辅助验证工具:ps(procps)、top、su

💡 技术拓展:Linux 调度优先级体系里,nice 值属于 SCHED_OTHER(分时调度)策略下的"相对让步量"。常见调度策略横向对比——

调度策略特点nice 值是否生效
SCHED_OTHER(CFS 分时)普通进程默认策略,按 nice 权重分享 CPU生效
SCHED_FIFO实时策略,先入先出、不抢占同优先级不生效
SCHED_RR实时策略,带时间片轮转不生效
SCHED_BATCH / SCHED_IDLE批处理/极低优先级后台弱相关

nice/renice 只对默认的 SCHED_OTHER 生效;实时策略需 chrt 且受严格权限控制,本文不展开。

二、命令概览

2.1 语法与测试数据

nice 的作用是:以指定的 nice 值增量启动命令。nice 值(niceness)范围 -20~19,数值越小越优先(-20 最高优先级,19 最低)。语法:

nice [OPTION] [COMMAND [ARG]...]    # OPTION 只有 -n/--adjustment 与 --help/--version

测试数据很简单:用一组 sleep 1000 后台进程当"演示负载",用 ps -o ni 读取每个进程的 NI 列验证调整结果。演示全程只新增独立进程,不改动系统已有进程。

2.2 --help 全量输出(逐行照抄)

$ nice --help; echo rc=$?
Usage: nice [OPTION] [COMMAND [ARG]...]
Run COMMAND with an adjusted niceness, which affects process scheduling.
With no COMMAND, print the current niceness.  Niceness values range from
-20 (most favorable to the process) to 19 (least favorable to the process).

Mandatory arguments to long options are mandatory for short options too.
  -n, --adjustment=N   add integer N to the niceness (default 10)
      --help     display this help and exit
      --version  output version information and exit

NOTE: your shell may have its own version of nice, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/nice>
or available locally via: info '(coreutils) nice invocation'
rc=0

逐段解读:

条目含义
With no COMMAND, print the current niceness不带命令时打印当前 nice 值(3.1 节实测)
-n, --adjustment=N ... (default 10)调整量 N 是增量而非目标值,省略 -n 时默认 +10
-20 ... 19nice 值边界:-20 对进程最有利,19 最不利,越界会被夹取(3.4/3.5 节实测)

2.3 版本信息

$ which nice
/usr/bin/nice

$ type nice
nice is /usr/bin/nice

$ type -a nice
nice is /usr/bin/nice
nice is /bin/nice

$ nice --version | head -2
nice (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.

type nice 实测返回 /usr/bin/nice——nice 不是 bash 内置命令,bash 中执行的就是这个 coreutils 外部命令(/bin/nice 与 /usr/bin/nice 在 Ubuntu 22.04 指向同一实体)。help 中的 NOTE 提示某些 shell(如 csh/tcsh)有自己的内置版 nice,行为可能与 coreutils 版略有差异;bash 用户无需担心。

三、参数逐项实测

3.1 无参数:显示当前 nice 值

不带命令执行 nice,打印"如果此时启动命令会继承"的当前 nice 值:

$ nice; echo rc=$?
0
rc=0

返回 0——普通进程的默认 nice 值。同时验证 nice 值会被子进程继承:

$ nice -n 3 bash -c "nice"
3

外层 nice 把 bash -c 的 nice 值抬到 3,内层 nice 读到的正是继承来的 3。

3.2 默认调整 +10

不带 -n 直接 nice 一个命令,默认增量是 +10(help 中 default 10)。启动一个普通对照进程和一个 nice 进程,用 ps -o ni 对比:

$ nice sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ ps -o pid,ni,cmd -p 18248,18250
    PID  NI CMD
  18248   0 sleep 1000
  18250  10 sleep 1000

验证闭环:同一时刻、同一用户,没加 nice 的进程 NI=0,加了 nice 的进程 NI=10——默认 +10 生效。NI=10 意味着它在 CPU 争抢时的权重明显低于普通进程。

3.3 -n / --adjustment=N:指定调整量

-n 与长选项 --adjustment 等价,指定增量(在当前值基础上加 N):

$ nice -n 5 sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ nice --adjustment=8 sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ ps -o pid,ni,cmd -p 18253,18267
    PID  NI CMD
  18253   5 sleep 1000
  18267   8 sleep 1000

验证结果:-n 5 与 --adjustment=8 分别得到 NI=5、NI=8,长短选项等效。注意 N 是增量:父进程 nice 值为 3 时,nice -n 5 的结果是 3+5=8(配合 3.1 节的继承特性理解)。

3.4 正值上界夹取(nice 值范围 -20~19)

nice 值合法范围是 -20~19,超出部分被内核夹取到边界。先实测正值上界:

$ nice -n 30 sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ ps -o pid,ni,cmd -p 18274
    PID  NI CMD
  18274  19 sleep 1000

请求 +30,实际 NI=19——被夹取到上界,不报错。调低优先级(正值)人人可用,这是 nice 最安全的使用面。

3.5 负值调整与权限边界(root 也可能 Permission denied)

负值(提高优先级)是特权操作。实测 root 在本环境尝试负值调整:

$ nice -n -5 sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ ps -o pid,ni,cmd -p 18270
    PID  NI CMD
  18270   0 sleep 1000

如实记录:root 执行 nice -n -5 后进程 NI 仍是 0,负值没有生效。原因是本环境 root 的有效能力集不含 CAP_SYS_NICE(内核据此拦截一切"降低 nice 值"的操作),可用 /proc 实测佐证:

$ grep CapEff /proc/self/status
CapEff:	00000000a80425fb

$ ulimit -e
0

$ ulimit -H -e
0

CapEff: 00000000a80425fb 中 bit23(CAP_SYS_NICE,对应 0x800000)为 0;同时 ulimit -e(RLIMIT_NICE 软/硬限制)均为 0,"抬升 RLIMIT_NICE 换取负值"这条路也被硬限制 0 封死(root 尝试 ulimit -e 40 实测报 ulimit: scheduling priority: cannot modify limit: Operation not permitted)。

⚠️ 注意:标准 Ubuntu 服务器上 root 默认持有 CAP_SYS_NICE,同样的 nice -n -5 会直接得到 NI=-5;nice -n -25 则会被夹取到下界 NI=-20(与 3.4 节正值夹取对称)。在降权加固的受控环境(如本实验环境)会遇到本节的 Permission denied 现象,排查方法见第五章 Q2。

3.6 老式写法:nice -7

POSIX 老式语法允许把增量直接写成单个 -数字 参数(省略 -n):

$ nice -7 sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ ps -o pid,ni,cmd -p 18277
    PID  NI CMD
  18277   7 sleep 1000

实测结果 NI=7——老式写法 nice -7 等价于 nice -n 7(增量 +7,不是 -7)。这个写法容易让人误读为负值,新脚本建议统一用 -n 明确语义。

3.7 普通用户:只能调高、不能调负

内核规则:无特权的普通用户只能调高(增大)自己进程的 nice 值,任何把 nice 值调小的尝试都会被拒绝。用演示用户 niceu1 实测:

$ su - niceu1 -c 'nice -n -5 sleep 1'; echo rc=$?
nice: cannot set niceness: Permission denied
rc=0

$ su - niceu1 -c 'nice -n 5 sleep 1'; echo rc=$?
rc=0

$ su - niceu1 -c 'nice; echo rc=$?'
0
rc=0

三条结论:

  1. nice -n -5:被拒绝,打印 nice: cannot set niceness: Permission denied;
  2. 注意 rc=0——nice 打印告警后仍会执行命令,只是 nice 值保持原值(对比 root 场景 3.5 节同样如此),所以脚本里不能靠返回码感知"调优先级失败",需要回读 ps -o ni 确认;
  3. nice -n 5(调高)静默成功,rc=0——普通用户调高不受限。

3.8 PR / NI / S 三列对照与技术拓展

本节回答"NI 调了之后,在各种工具里怎么读"。给一组不同 NI 的进程同时打印 pid, pri, ni, stat:

$ ps -o pid,pri,ni,stat,cmd -p 18248,18250,18253,18270,18272,18274
    PID PRI  NI STAT CMD
  18248  19   0 S    sleep 1000
  18250   9  10 SN   sleep 1000
  18253  14   5 SN   sleep 1000
  18270  19   0 S    sleep 1000
  18272  19   0 S    sleep 1000
  18274   0  19 SN   sleep 1000

$ top -b -n 1 -p 18250,18270,18272 | head -12
top - 10:11:48 up  3:55,  4 users,  load average: 0.99, 0.92, 1.21
Tasks:   3 total,   0 running,   3 sleeping,   0 stopped,   0 zombie
%Cpu(s):  3.3 us,  1.1 sy,  0.0 ni, 95.0 id,  0.0 wa,  0.0 hi,  0.6 si,  0.0 st
MiB Mem :  40066.4 total,   8103.3 free,   9229.8 used,  22733.3 buff/cache
MiB Swap:   2048.0 total,   2042.5 free,      5.5 used.  30181.2 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  18250 root      30  10    2792   1672   1584 S   0.0   0.0   0:00.00 sleep
  18270 root      20   0    2792   1672   1576 S   0.0   0.0   0:00.00 sleep
  18272 root      20   0    2792   1664   1568 S   0.0   0.0   0:00.00 sleep

用补充实测(ps -o pri,opri 双列)把口径对齐:

$ ps -o pid,ni,pri,opri,cmd -p 498
    PID  NI PRI PRI CMD
    498   5  14  85 sleep 1000

💡 技术拓展:ps/top 里与优先级相关的三列(常一起出现)含义与实测口径——

列含义实测换算关系(本环境)方向
NInice 值,-20~19,用户可用 nice/renice 调整即 nice 值本身越小越优先
PR(top)/ PRI(ps)调度优先级的工具展示口径top PR = 20 + NI;ps PRI = 19 − NI;ps opri = 80 + NI见方向列
S(STAT)进程状态:R 运行 / S 睡眠 / D 不可中断 / Z 僵尸 / T 停止与优先级无关,排查时用来区分"没轮到 CPU"还是"卡在 IO"—

内核内部对 SCHED_OTHER 进程的动态优先级为 120 + NI(范围 100~139,数值越小越优先,见 sched(7));top 的 PR 与 ps 的 PRI/opri 是对该值的不同展示换算。横向比较优先级时,以 NI 为准最不易出错:NI 越小,CPU 争抢时分配到的份额越大。

上表实测数据点:NI 0→PRI 19/PR 20;NI 5→PRI 14/opri 85;NI 10→PRI 9/PR 30;NI 19→PRI 0。STAT 列中 S=睡眠、SN=睡眠+低优先级(nice 调整过的进程会带 N 标记)。

3.9 nice 对已运行进程无效(只能 renice)

nice 只作用于"它启动的那个命令",进程一旦跑起来,nice 就管不了了。用 ps 自身做演示:给 ps 加 nice -n 1,目标进程的 NI 纹丝不动:

$ nice -n 1 ps -o pid,ni,cmd -p 18250
    PID  NI CMD
  18250  10 sleep 1000

$ ps -o pid,ni,cmd -p 18250
    PID  NI CMD
  18250  10 sleep 1000

💡 技术拓展:nice 与 renice 的分工对照——

维度nicerenice
作用对象只能是它新启动的命令已在运行的进程/用户/进程组
典型时机启动时预设(跑批、备份)运行中干预(降载、提权)
调低(负值)能力同受 CAP_SYS_NICE/RLIMIT_NICE 约束同受约束
归属包GNU coreutils 8.32util-linux 2.37.2(本环境实测)

记忆口诀:"启动用 nice,运行中用 renice"。renice 的逐参数实测见《renice 命令详解与参数实测(Ubuntu 22.04)》。

四、实战示例

4.1 低优先级跑批:把备份/压缩对线上影响降到最低

夜间批处理、大文件压缩等非紧急任务,用最大 nice 值启动,CPU 紧张时自动让路:

$ nice -n 19 sleep 300 >/dev/null 2>&1 & sleep 0.3

$ ps -o pid,ni,cmd -p 110
    PID  NI CMD
  110  19 sleep 300

NI=19 是对进程"最不利"的合法值,无需特权(正值人人可调)。实际业务里把 sleep 300 换成备份脚本即可。

4.2 nice 值继承链验证

nice 值随 fork 继承,可用来给"整棵进程树"预设优先级:

$ nice -n 3 bash -c "nice"
3

外层调了 +3,里层 nice 读到 3——之后该 shell 启动的所有子进程都从 3 起步。包装脚本时只需在最外层 nice 一次。

4.3 先 nice 启动、后 renice 修正(含权限现实)

先用 nice 预设一个 NI=10 的任务(默认增量),运行中想改判时就得换 renice:

$ nice sleep 300 >/dev/null 2>&1 & sleep 0.5

$ ps -o pid,ni,cmd -p 119
    PID  NI CMD
  119  10 sleep 300

假设发现这个任务其实重要,想调回 NI=5——调低需要特权,在 3.5 节所述的受限能力环境下会被拒绝,如实记录:

$ renice -n 5 -p 119
renice: failed to set priority for 119 (process ID): Permission denied

$ ps -o pid,ni,cmd -p 119
    PID  NI CMD
  119  10 sleep 300

⚠️ 注意:标准 root 服务器(持有 CAP_SYS_NICE)上同样的命令会返回 119 (process ID) old priority 10, new priority 5 并即时生效。

调高方向则畅通无阻(不需要任何特权)。renice 独立实测记录中,把一个 NI=5 的进程调到 9 的真实回显:

$ ps -o pid,ni,cmd -p 18318
    PID  NI CMD
  18318   5 sleep 1000

$ renice 9 -p 18318
18318 (process ID) old priority 5, new priority 9

组合拳总结:nice 负责"出生时的起点"(无门槛),renice 负责"运行中的改判"——调高人人可做,调低需要 CAP_SYS_NICE 或相应 RLIMIT_NICE。renice 的逐参数实测详见《renice 命令详解与参数实测(Ubuntu 22.04)》。

4.4 场景四:后台跑批的 NI 核查

后台批处理任务启动后,运维需要确认"nice 是否真的生效"。单进程核查(3.2 节实测形态):

$ nice sleep 1000 >/dev/null 2>&1 & sleep 0.2

$ ps -o pid,ni,cmd -p 18250
    PID  NI CMD
  18250  10 sleep 1000

多进程批量核查时,把 PID 列表传给同一个 ps(3.2 节实测形态):

$ ps -o pid,ni,cmd -p 18248,18250
    PID  NI CMD
  18248   0 sleep 1000
  18250  10 sleep 1000

💡 要点:NI 列是核查 nice 生效与否的唯一权威依据(3.7 节提醒过:nice 调整失败只打印告警、返回码仍是 0,脚本化核查必须回读 NI)。想进一步看调度表现,再用 3.8 节的 pid,pri,ni,stat 多列口径。

五、注意事项与常见问题

Q1:nice 值和进程优先级到底是什么关系? nice 值是用户态的"让步量"(-2019,越小越优先),内核把它换算为动态优先级 120+NI(100139)参与 CFS 调度权重计算。NI 每小 1,争抢时权重提升约 10%(相对值),但它不改变进程的实时性——需要硬实时请用 chrt 走 SCHED_FIFO/RR。

Q2:为什么 root 执行 nice -n -5 也报 Permission denied / 不生效? 内核要求"降低 nice 值"的调用方持有 CAP_SYS_NICE,或 RLIMIT_NICE 允许。本环境实测 root 的 CapEff: 00000000a80425fb 不含该位、ulimit -e 软硬限制均为 0(3.5 节)。排查方法:grep CapEff /proc/self/status 对照 CAP_SYS_NICE(bit23,0x800000),ulimit -e 与 ulimit -H -e 查看限制。标准服务器上 root 默认持有该能力,直接生效;受控环境需管理员授予能力或放开 RLIMIT_NICE。

Q3:nice 是 bash 内置命令吗? 不是。type nice 实测返回 nice is /usr/bin/nice(2.3 节),bash 执行的是 coreutils 外部命令;csh/tcsh 才有内置版 nice(help 的 NOTE 所指)。这解释了为什么 nice 的报错格式是 coreutils 风格(Try 'nice --help')。

Q4:nice -n 10 不带命令为什么报错? 增量与命令必须成对出现——nice 需要一个命令作为"载体"。实测:

$ nice -n 10; echo rc=$?
nice: a command must be given with an adjustment
Try 'nice --help' for more information.
rc=125

rc=125 表示命令用法错误。只想查看当前值时用不带 -n 的裸 nice(3.1 节)。

Q5:明明调了 nice 值,为什么看不到性能变化? NI 只在 CPU 争抢时起作用。CPU 空闲(如 3.8 节 top 显示 95.0 id)时每个进程都能随时上 CPU,NI=19 与 NI=0 的响应没有肉眼差别;NIC 也不影响内存、磁盘、网络带宽的分配——瓶颈在 IO 时调 nice 无效,需 cgroup/iolimit 类工具。

六、参考链接