如何阻止iscsiadm执行时向dmesg写日志并输出到所有终端
执行sudo iscsiadm -m discovery -t st -p <IP> -l命令时,dmesg内核日志会输出到服务器所有终端,日志格式为[some_num.some_dec] LOG_MESSAGE,会覆盖终端提示符,影响正常系统调试。
该命令由Java应用调用,调用代码如下:
Runtime.getRuntime().exec("/bin/bash", "-c", "sudo iscsiadm -m discovery -t st -p *IP* -l");
已尝试的无效解决方法:
- 在
iscsiadm discovery命令末尾追加> /dev/null 2>&1重定向输出 - 捕获返回进程的输入流
process.getInputStream()和错误流process.getErrorStream() - 在Jar包启动命令后追加
> /dev/null 2>&1重定向输出
上述方案全部无效的核心原因是:这类跨终端打印的日志不是iscsiadm用户态进程产生的stdout/stderr输出,而是内核直接生成的printk日志。默认配置下,优先级高于阈值的内核日志会被直接写入所有活跃虚拟终端的tty设备,完全不经过用户态进程的输出通道,因此常规的用户态输出重定向、流捕获手段无法拦截。
可根据实际场景选择对应方案,按影响范围从小到大排序:
1. 单终端临时屏蔽
如果只需要在当前操作的终端屏蔽日志,执行以下命令调整内核控制台打印级别即可:
dmesg -n 1
内核日志级别说明:数值越小优先级越高,1为致命错误,2为严重错误,3为普通错误,4为警告,5为通知,6为常规信息,7为调试信息。系统默认控制台打印级别为4,即优先级≥4的日志都会输出到终端。设置为1后仅致命系统错误会打印到终端,iscsi连接产生的常规信息级日志不会再弹出。
需要恢复默认级别时执行dmesg -n 4即可。
2. Java调用时临时调整级别(推荐)
不需要修改系统全局配置,直接调整Java调用的命令逻辑,在执行iscsiadm操作前临时降低控制台日志级别,操作完成后自动恢复,对其他业务无影响。修改后的bash命令为:
/bin/bash -c "dmesg -n 1; sudo iscsiadm -m discovery -t st -p *IP* -l; dmesg -n 4"
对应Java代码修改为:
Runtime.getRuntime().exec("/bin/bash", "-c", "dmesg -n 1; sudo iscsiadm -m discovery -t st -p *IP* -l; dmesg -n 4");
注意需要保证执行命令的用户拥有调整内核日志级别的权限,sudo执行即可。
3. 全局永久屏蔽
如果需要所有终端永久不再打印非致命内核日志,可修改sysctl配置:
- 编辑
/etc/sysctl.conf文件,添加或修改以下配置项:
四个参数分别对应:控制台日志级别、默认消息日志级别、最小允许控制台日志级别、启动时默认控制台日志级别。kernel.printk = 1 4 1 7 - 执行
sysctl -p加载配置,立即生效。
4. 仅过滤iscsi相关日志
如果不想调整全局日志级别,只屏蔽iscsi相关的终端日志输出,可通过rsyslog配置规则过滤:
- 新建rsyslog配置文件
/etc/rsyslog.d/00-block-iscsi.conf - 写入以下规则,阻止iscsi相关日志转发到终端设备:
:msg, contains, "iscsi" stop - 执行
systemctl restart rsyslog重启服务生效。
内容的提问来源于stack exchange,提问作者Kris Rice

