nice 命令详解与参数实测(Ubuntu 22.04)
逐项实测 Ubuntu 22.04 的 nice(GNU coreutils 8.32):无参查看当前值、默认 +10、-n/--adjustment 指定调整量、正值夹取上界 19、负值与权限边界(CapEff 排查法)、普通用户只能调高不能调负、PR/NI/S 三列口径对照与老式写法,附低优先级跑批等实战场景与常见问题排查。
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 ... 19 | nice 值边界:-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
三条结论:
nice -n -5:被拒绝,打印nice: cannot set niceness: Permission denied;- 注意 rc=0——nice 打印告警后仍会执行命令,只是 nice 值保持原值(对比 root 场景 3.5 节同样如此),所以脚本里不能靠返回码感知"调优先级失败",需要回读
ps -o ni确认; 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 里与优先级相关的三列(常一起出现)含义与实测口径——
列 含义 实测换算关系(本环境) 方向 NI nice 值,-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 的分工对照——
维度 nice renice 作用对象 只能是它新启动的命令 已在运行的进程/用户/进程组 典型时机 启动时预设(跑批、备份) 运行中干预(降载、提权) 调低(负值)能力 同受 CAP_SYS_NICE/RLIMIT_NICE 约束 同受约束 归属包 GNU coreutils 8.32 util-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 类工具。
六、参考链接
- Ubuntu 22.04 (jammy) nice 手册页:https://manpages.ubuntu.com/manpages/jammy/en/man1/nice.1.html
- GNU coreutils 官方手册 nice 章节:https://www.gnu.org/software/coreutils/manual/html_node/nice-invocation.html
- setpriority(2) 系统调用(nice 值与权限规则):https://man7.org/linux/man-pages/man2/setpriority.2.html
- sched(7) 调度策略与优先级范围:https://man7.org/linux/man-pages/man7/sched.7.html