Linux
阅读提示
建议先看题目目录,再按“概念 -> 原理 -> 场景 -> 优化”顺序复习。
每题先讲结论,再补关键机制和项目实践,回答会更稳。
本文命令以 Linux 上的 Bash 5.x、GNU coreutils 9.x、procps-ng 4.x、iproute2 6.x 和 util-linux 2.39+ 为适用环境;BusyBox、BSD 工具的选项可能不同。Java 诊断部分以 HotSpot JDK 17/21 为准,调度算法另注明内核版本。
1、绝对路径用什么符号表示?当前目录、上层目录用什么表示? 主目录用什么表示? 切换目录用什么命令? (了解)
- 绝对路径:以
/开头,如/etc/init.d。 - 当前目录和上层目录:
./../ - 主目录:在 Bash 中,未加引号的
~/会展开为当前用户的主目录;~是 Shell 展开语法,不是绝对路径的起始符。 - 切换目录:
cd
2、 怎么查看当前进程?怎么执行退出?怎么查看当前路径?
- 查看当前进程:
ps ps默认查看与当前用户及终端关联的进程;ps -l使用长格式,并不表示本次登录的全部进程。ps aux或ps -ef可查看所有进程快照,避免混用有歧义的ps -aux。按名称查询可用pgrep -a java;grep *会受到 Shell 通配符展开影响,不是进程查询语法。top持续刷新 CPU、内存等指标。结束进程通常先用kill -TERM PID请求正常退出;kill -KILL PID(即kill -9)无法被捕获,不能执行应用清理逻辑,仅在必要时使用。- 执行退出:
exit - 查看当前路径:
pwd
3、查看文件有哪些命令?
vi 文件名#编辑方式查看,可修改cat 文件名#显示全部文件内容more 文件名#分页显示文件内容less 文件名#分页查看,支持前后翻页和搜索tail 文件名#仅查看尾部,还可以指定行数head 文件名#仅查看头部,还可以指定行数
4、列举几个常用的Linux命令
ls: 列出当前目录下的文件和子目录信息。- 使用方式:
ls [-options] [file/directory] - 示例:
ls /home/user列出/home/user目录下非隐藏条目的信息;包含隐藏条目可用ls -a。 cd: 切换当前工作目录。- 使用方式:
cd [directory] - 示例:
cd Documents切换到Documents目录,使用cd ..返回上一级目录。 pwd: 显示当前工作目录的绝对路径。- 使用方式:
pwd mkdir: 创建新的目录。- 使用方式:
mkdir [directory] - 示例:
mkdir javacn创建 “javacn” 文件夹。 touch: 创建新文件或者更新已存在文件的时间戳。- 使用方式:
touch [file] - 示例:
touch newfile.txt rm: 删除指定的文件或目录。- 使用方式:
rm [-options] file/directory - 示例:
rm file.txt(删除单个文件)、rm -r directory(递归删除目录及其内容)。 cp: 复制文件或目录。- 使用方式:
cp [-options] source destination - 示例:
cp file1.txt file2.txt(复制文件)、cp -r dir1 dir2(复制目录) mv: 移动或重命名文件或目录。- 使用方式:
mv [-options] source destination - 示例:
mv file.txt newfile.txt(重命名文件)、mv file.txt /dir/(移动文件到指定目录)。 find: 在指定目录下查找满足条件的文件。- 使用方式:
find [path] [expression] - 示例:
find . -name "*.txt"在当前目录及其子目录下查找扩展名为.txt的文件。 grep: 搜索文件中匹配特定模式的行。- 使用方式:
grep [options] pattern file(s) - 示例:
grep "hello" file.txt在file.txt中查找包含 “hello” 的行。
5、你平时是怎么查看日志的?
- Linux查看日志的命令有多种:
tail、cat、tac、head(echo用于输出参数,并不读取日志文件) 等,本文只介绍几种常用的方法 1、tail- 最常用的一种查看方式 命令格式:
tail [选项] [文件] -f持续跟踪新增内容,-q不输出文件名首部,-v总是输出文件名首部;-c<数目>显示的字节数-n<行数>显示行数-q, --quiet, --silent从不输出给出文件名的首部-s, --sleep-interval=S与-f合用,表示在每次反复的间隔休眠S秒- 例如:
tail -n 10 test.log查询日志尾部最后10行的日志;tail -n +10 test.log从第10行开始输出(包含第10行);tail -n 10 -f test.log先显示最后10行,再持续输出新增内容
一般还会配合着 grep 搜索用,例如:
tail -n 1000 -F test.log | grep --line-buffered '关键字'(GNU grep 的--line-buffered可减少管道输出缓冲延迟)
GNU tail -f 默认跟踪已打开的文件描述符。日志轮转若将 test.log 重命名并新建同名文件,旧描述符仍指向旧文件;-F 等价于 --follow=name --retry,会尝试按名称重新打开,因此更适合这类轮转。轮转期间仍可能存在观察间隙,不能当作可靠的日志采集协议。参考:GNU tail 手册。
test.log → 重命名为 test.log.1;新建 test.log
-f → 继续跟踪旧文件描述符
-F → 检测名称变化并尝试重新打开 test.log如果一次性查询的数据量太大,可以进行翻页查看,例如:
tail -n 4700 aa.log | less分页显示最后4700行,空格向前翻页,q退出2、head跟
tail是相反的head是看前多少行日志head -n 10 test.log查询日志文件中的头10行日志;head -n -10 test.log查询日志文件除了最后10行的其他所有日志;head与tail的选项并不完全相同,例如head不支持-f跟踪。3、catcat是由第一行到最后一行连续显示在屏幕上一次显示整个文件 :
$ cat filename从键盘创建一个文件 :
$cat > filename将几个文件合并为一个文件:
cat file1 file2 > file:目标不存在时创建,已存在时覆盖;目标不能同时作为输入文件将一个日志文件的内容追加到另外一个 :
cat -n textfile1 >> textfile2(追加带行号的内容)清空一个日志文件:
: > textfile2(Bash 空命令配合重定向,将文件截断为零字节)注意:
>默认创建或截断覆盖文件(设置noclobber时行为不同),>>创建或追加。千万不要弄混了。cat的常用选项有-n(所有行编号)和-b(仅非空行编号),不能照搬tail的选项。
重定向由 Shell 在执行命令前处理,覆盖输入文件会先截断它。参考:GNU Bash 重定向。
4、moremore是分页显示文本的工具,它以全屏幕的方式按页显示文本文件的内容,支持vi中的关键字定位操作。more命令中内置了若干快捷键,常用的有H(获得帮助信息),Enter(向下翻滚一行),空格(向下滚动一屏),Q(退出命令)。more按需读取,并不要求启动时加载整个文件;常规文件可向后翻页,管道等不可定位的输入存在限制。- 该命令一次显示一屏文本,满屏后停下来,并且在屏幕的底部出现一个提示信息,给出至今己显示的该文件的百分比:
--More--(XX%) more的语法:more 文件名Enter向下n行,需要定义,默认为1行Ctrl f向下滚动一屏- 空格键 向下滚动一屏
Ctrl b返回上一屏=输出当前行的行号:f输出文件名和当前行的行号v调用vi编辑器!命令调用Shell,并执行命令q退出more
5、sed这个命令可以查找日志文件特定的一段 , 根据时间的一个范围查询,可以按行号或文本模式范围查询
按照行号
sed -n '5,10p' filename这样你就可以只查看文件的第5行到第10行。按照时间段
sed -n '/2014-12-17 16:17:20/,/2014-12-17 16:17:36/p' test.log这里匹配的是起止行的正则文本,并不解析时间;两端都包含。结束模式缺失时会一直输出到文件末尾,起始模式缺失时不会自动选取区间内其他时间的日志。参考:GNU sed 地址范围。
6、lessless命令在查询日志时,一般流程是这样的less log.logshift + G命令到文件尾部 然后输入?加上你要搜索的关键字例如?1213按
n向上查找关键字shift+n反向查找关键字less与more类似,使用less可以随意浏览文件,more也能在可定位文件中向后翻页;两者都不要求预先读取整个文件。less更适合交互式搜索和回看。less log2013.log查看文件ps -ef | lessps查看进程信息并通过less分页显示history | less查看命令历史使用记录并通过less分页显示less log2013.log log2014.log浏览多个文件常用命令参数:
-b <缓冲区大小>设置缓冲区的大小-g只高亮当前搜索定位到的匹配项,而非屏幕上所有匹配项-i搜索模式不含大写字母时忽略大小写;-I始终忽略大小写-m显示类似more命令的百分比-N显示每行的行号-o <文件名>将管道输入记录到文件,仅适用于管道输入,不是保存屏幕排版结果-Q不使用警告音-s显示连续空行为一行/字符串:向下搜索"字符串"的功能?字符串:向上搜索"字符串"的功能n:重复前一个搜索(与/或?有关)N:反向重复前一个搜索(与/或?有关)b向后翻一页h显示帮助界面q退出less命令
一般本人查日志配合应用的其他命令
history// 当前 Shell 保存的历史记录,受历史配置与容量限制history | grep XXX// 历史记录中包含某些指令的记录history | more// 分页查看记录history -c// 清空所有的历史记录!!重复执行上一个命令!323重新执行历史编号323对应的命令(Bash 交互式历史展开)
6、Linux上如何查询某个端口是否被占用?
优先使用 iproute2 的 ss,例如查询本地8080端口:
ss -ltnp 'sport = :8080' # TCP 监听套接字
ss -aunp 'sport = :8080' # UDP 套接字(包括已连接的 UDP)-n 显示数字端口,-p 请求进程信息;查看其他用户进程可能需要相应权限。应同时确认本地地址、IPv4/IPv6 和协议;TCP 未监听也可能已绑定或处于其他状态,可再用 ss -tanp 'sport = :8080' 检查。没有监听输出不能直接保证下一次绑定成功。
已安装 net-tools 时也可用 netstat -tulnp,原来的 -tuln 没有 -p,不会显示 PID/程序名。按数字 grep 还可能误匹配其他端口。ps aux | grep 8080 仅搜索命令行文字,不能判断套接字占用。
参考:iproute2 ss 手册。
7、实际工作中如何排查CPU飙升问题?
以 Linux 上的 HotSpot JDK 17/21 为例,先用 top(按 P 以 CPU 排序)定位进程,再用 top -H -p PID 观察线程。线程的 CPU 时间统计和线程栈是两个时刻的快照,需要多次采样才能判断热点,不能仅凭线程状态认定死循环。
# PID=1234、TID=1256 仅为占位示例,替换为现场观察到的值
printf '%x\n' 1256 # 十进制 Linux TID 转十六进制
jcmd 1234 Thread.print -l # 在完整线程栈中搜索 nid=0x4e8
jstat -gcutil 1234 1000 5 # 每秒一次,共5次,观察 GC 统计变化
jcmd 1234 GC.heap_info # 堆概况平台线程栈中的 nid 对应 Linux 原生线程 ID,十六进制转换后可关联线程并保留完整调用栈;只 grep 线程标题会丢失定位所需的栈帧。JDK 21 的虚拟线程不与 OS 线程一一对应,这个方法主要定位承载它们的平台线程。
jmap -heap 不是 JDK 17/21 的有效用法,使用上述 GC.heap_info。仅在确需分析堆对象时考虑 jcmd 1234 GC.heap_dump /path/to/heap.hprof;堆转储影响较大,默认可能触发 Full GC,并占用磁盘,不能作为 CPU 飙升时必做步骤。jcmd 需要在 JVM 所在机器上以相同有效用户和组运行,容器中还需注意 PID 命名空间;可用 jcmd PID help 核对目标 JVM 支持的命令。
8、场景题:项目本地能运行,发布到Linux后运行不了,可能是什么原因?该如何解决?
- 环境差异:本地环境和服务器环境可能存在差异,例如Java版本、系统环境变量、依赖库等。解决方法是确保服务器环境和本地环境尽可能一致
- 权限问题:可能是Linux服务器上的文件权限或者防火墙设置导致的。解决方法是检查并修改相关的权限设置
- 依赖问题:可能是项目依赖的库在服务器上不存在或版本不匹配。解决方法是检查项目的依赖,并确保它们在服务器上正确地被安装和配置
- 配置问题:可能是配置文件中的路径、数据库连接信息等在服务器上不适用。解决方法是检查并修改配置文件,确保它们在服务器环境中是正确的
8、什么是零拷贝技术?它有哪些使用场景?
- 零拷贝技术是一种优化数据传输的方法,它通过最小化数据在内存中的拷贝次数来提高数据传输的效率和性能。通常,在数据传输过程中,数据需要从一个缓冲区(如内核缓冲区)拷贝到另一个缓冲区(如用户空间缓冲区),然后再传输到目标位置。而零拷贝技术的目标是尽可能减少或消除这些拷贝操作,从而降低系统开销和提高性能。零拷贝技术的使用场景包括但不限于以下几种:
- 网络数据传输:在网络传输过程中,零拷贝技术可以避免数据在内核空间和用户空间之间的拷贝,从而提高网络数据传输的效率。常见的应用包括高性能网络服务器、网络流媒体服务等
- 文件传输:在文件传输过程中,零拷贝技术可以减少数据在文件系统缓存和用户空间缓冲区之间的拷贝次数,提高文件传输的效率。例如,在文件系统中实现零拷贝的技术可以加速文件的读取和写入操作
- 内存映射文件:内存映射文件是一种将文件映射到进程地址空间的技术,可以让应用程序直接操作文件而无需进行显式的读写操作。映射文件页可省去将文件内容读入独立用户缓冲区的一次复制,但仍有缺页处理等成本
- 数据库系统:在数据库系统中,零拷贝技术可以用于加速数据的读取和写入操作,提高数据库的性能和吞吐量。例如,采用内存映射文件的数据库可减少文件页与独立用户缓冲区之间的复制;实际收益取决于缓存、事务和 I/O 实现
以 Linux sendfile() 为例,数据在内核内从输入文件描述符传到输出描述符,避免 read() 到用户缓冲区后再 write() 回内核的往返拷贝;并不保证磁盘、内存、网卡之间完全没有数据搬运。mmap() 则把文件页映射到地址空间,也不等于自动实现文件到网络的零拷贝。应用若需在用户态修改数据,仍可能需要额外拷贝;数据库是否受益取决于实际 I/O 路径,不能一概而论。sendfile() 成功也可能只发送部分数据,调用方需处理短传输;Linux 2.6.33 起输出描述符不再局限于套接字。参考:Linux man-pages sendfile(2)。
9、Linux 调度程序是根据进程的动态优先级还是静态优先级来调度进程的?(了解)
不能概括为“统一按动态优先级调度”,需要区分调度策略;Linux 实际调度的是可运行线程。
- 普通线程(
SCHED_OTHER):Linux 2.6.23 引入 CFS,以 nice 值决定权重,通过虚拟运行时间分配 CPU;nice 较小通常意味着较大份额,并非永远先执行。 - Linux 6.6 起普通公平调度开始转向 EEVDF:先用 lag 判断线程是否应得到 CPU(lag ≥ 0 为 eligible),再从 eligible 线程中选择虚拟截止时间最早者。该截止时间用于公平调度,不是应用的实时期限。
- 实时线程(
SCHED_FIFO/SCHED_RR)使用静态实时优先级,同优先级分别按 FIFO 或时间片轮转;SCHED_DEADLINE则按运行预算、周期和截止时间等参数调度,不能套用普通线程的 nice 规则。
参考:内核 CFS 文档、内核 EEVDF 文档。发行版可能回移补丁,实际实现还应结合发行版内核源码确认。
