【大前端 nodejs】linux面试真题
前言
题目均是真题,职位为Node.js开发、全栈(node.js + react)、大前端(需要会node.js的前端职位)中的关于linux的面试题。
我是为了拓宽自己的将来的就业面哈哈,其实本质来说完全具备全栈的能力了,所以总结一波node.js相关的面试题,整体难度偏初级和中级。既然是服务端,linux基础命令的问题肯定跑不脱。
本文记录在node面试题系列里
频率最高的题:请说一下你常用的linux命令
这个自由发挥吧,常用的不就是cd、ls、vim这些命令吗。。。 不过你不是非常熟悉的命令不要说,面试官会接着问,比如你说ps命令,他会问ps -ef和ps -aux的差别等等
LINUX这边常用的查看日志的指令
tail
: 用于查看日志文件的末尾内容,通常用于实时监控日志文件的变化,常与-f
选项一起使用,实时输出新增的日志信息。例如,tail -f /var/log/syslog
可以实时查看系统日志文件的更新内容。grep
: 用于在文本中搜索指定的模式,通常用于从日志文件中查找特定的信息。例如,grep "error" /var/log/syslog
可以查找系统日志文件中包含"error"关键词的信息。
切记: 实时输出新增的日志信息是一个非常实用的命令,并且面试很常见,一定要记住。
LINUX怎么杀掉一个进程
常见的就是 kill -15 pid
面试官会追问如何强杀一个进程,可以用 kill -9 pid, 我们顺便普及一下kill和信号是什么.
常见的信号
上面的 -9代表的是SIGKILL信号,-15代表的是SIGTERM信号,我们在使用nodejs的时候,通常会有在写代码时,可能执行退出命令,这时候就需要传一个信号量,就可以用我们这里的学到的9和15传递给它。
在 Node.js 中,
process.exit()
方法用于终止当前进程,传递给该方法的数字参数表示进程的退出码。在这种情况下,process.exit(15)
和process.exit(2)
的区别在于它们返回的退出码不同。
在 Unix/Linux 系统中,15 号信号(SIGTERM)表示终止进程的请求,而 2 号信号(SIGINT)表示中断进程的请求。因此,
process.exit(15)
表示进程接收到终止请求,而process.exit(2)
表示进程接收到中断请求。
简单来说SIGTERM:当前进程接收到这个信号时,大多会先释放自己的资源,再停止进程,属于正常关闭。但有时候,可能这个进程正在进行一些I/O操作所以不能立即关闭。
这时候SIGKILL:属于强制关闭进程,不管你现在是啥情况。
linux下进程间通信方式?管道、共享内存什么场景下会用?两个进程不在同一个机器如何通信?
- 管道(Pipe):管道是一种半双工的通信方式,通常用于父子进程之间或者兄弟进程之间的通信。它的特点是只能在具有亲缘关系的进程之间使用,而且数据只能在一个方向上流动。
- 命名管道(Named Pipe):命名管道是一种特殊的文件,可以被多个进程共享访问,可以用于非亲缘关系进程之间的通信。
- 共享内存(Shared Memory):共享内存是一种快速的进程间通信方式,它将一段内存区域映射到多个进程的地址空间中,多个进程可以直接读写这段共享内存,以达到高效的通信目的。
- 消息队列(Message Queue):消息队列是一种基于消息的通信方式,它允许进程将消息发送到一个队列中,供其他进程读取。
- 套接字(Socket):套接字是一种通用的进程间通信方式,可以在本地或者远程不同的主机之间通信。
对于管道和共享内存,它们的使用场景如下:
- 管道适用于数据流式的场景,比如父子进程之间的通信,或者进程输出传递给另一个进程进行处理等。
- 共享内存适用于大量数据的读写场景,比如多个进程需要频繁地读写共享的数据区域,共享内存可以提高数据传输的效率。(在nodejs中主要体现在sharedArrayBufferr实现多个worker共享数据)
这里补充一下,node.js在linux下使用了Socket实现了IPC,并且内部它们与网络 socket 的行为比较类似,属于双向通信。不同的是它们在系统内核中就完成了进程间的通信,而不经过实际的网络层,非常高效。在 Node 中,IPC 通道被抽象为 Stream 对象。
不在一个机器可以使用socket通信,比如使用nodejs的net模块。
进程通信:信号、信号量是什么,进程间通信消息队列机制的本质是什么?
信号是IPC通信的一种机制,信号量是一种用于进程间同步和互斥的机制。
信号(Signal)是一种在进程间通信中用于处理异步事件的机制。当某个进程需要向另一个进程发送通知时,可以通过向该进程发送信号来实现。信号是一种软件中断,可以被操作系统或其他进程发送,并被接收进程处理。
Linux 中常见的信号包括 SIGINT
、SIGTERM
、SIGKILL
等,这些信号通常用于终止进程或处理其他进程间的通知事件。
信号量(Semaphore)是一种用于进程间同步和互斥的机制。它是一个计数器,用于控制多个进程对共享资源的访问。当一个进程进入临界区时,它会将信号量的值减一,表示已经使用了共享资源;当进程退出临界区时,它会将信号量的值加一,表示该共享资源已经释放。其他进程可以通过等待信号量变为可用状态,然后再进入临界区。
进程间通信消息队列机制的本质
消息队列是 Linux 进程间通信的一种方式,它允许多个进程通过向共享的队列中发送和接收消息来进行通信。
在 Linux 中,消息队列本质上是由内核维护的一段缓冲区,是存放在内存中的消息链表。
- 消息队列允许一个或多个进程向它写入或读取消息。
- 消息队列可以实现消息的「随机查询」,不一定非要以先进先出的次序读取消息,也可以按消息的类型读取。比有名管道的先进先出原则更有优势。
- 消息队列的生命周期随内核,如果没有释放消息队列或者没有关闭操作系统,消息队列就会一直存在。而匿名管道随进程的创建而建立,随进程的结束而销毁。
如何查看linux进程信息,其中vsz和rss有什么区别?
我一般是用 ps -aux,能看到的信息更全一些。
其中ps -aux 命令会显示vsz和rss两个指标的信息,简单来说rss就是程序实际上使用的内存,包括堆栈,动态链接库和本身正在内存里的代码大小。vsz会更大一些,因为它不管你实际用到多少,而是你整个代码引用了哪些动态链接库,使用了的全部代码,不管有没有在内存(有些存在磁盘上),都算进来了,并且vsz还包括了虚拟内存。
所以整体来看rss更能反映真实的代码内存占用情况。
示例如下:
假设进程A的二进制文件是500K,并且链接了一个2500K的动态库,堆和栈共使用了200K,其中100K在内存中(剩下的被换出或者不再被使用),一共加载了动态库中的1000K内容以及二进制文件中的400K内容至内存中,那么:
RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K
Linux文件描述符是什么
一个 Linux 进程启动后,会在内核空间中创建一个 PCB 控制块,PCB 内部有一个文件描述符表(File descriptor table),记录着当前进程所有可用的文件描述符,即当前进程所有打开的文件。
除了文件描述符表,系统还需要维护另外两张表:
-
打开文件表(Open file table)
-
i-node 表(i-node table)
文件描述符表每个进程都有一个,打开文件表和 i-node 表整个系统只有一个,它们三者之间的关系如下图所示。
从本质上讲,这三种表都是结构体数组,0、1、2、73、1976 等都是数组下标。表头只是我自己添加的注释,数组本身是没有的。实线箭头表示指针的指向,虚线箭头是我自己添加的注释。
你看,文件描述符只不过是一个数组下标吗!
所以最终文件描述符找到了i-node表里的对应信息。
inode 表包含文件名、文件大小、文件创建时间、文件所有者、文件权限等。每个文件在文件系统中都有唯一的 inode 号,通过 inode 号可以找到该文件的所有元数据和数据块信息。当进程打开一个文件时,内核会从文件系统中查找该文件对应的 inode 号,并将其记录在文件的表项中,以便进行后续的文件操作。
linux查找文件的指令
find命令,常见的使用 -name 根据文件名查询,或者 -size 根据文件大小查询。
将当前目录及其子目录下所有最近 20 天内更新过的文件列出:
find . -ctime 20
Linux下查看网络端口?
一般都是用netstat,我简单来讲一下这个命令吧,这个也是非常容易考到的题。
含义:
netstat命令用于显示网络状态,在工作中经常要查看端口的占用情况,比如启动一个应用避免端口冲突。
常用参数:
- -t 显示tcp传输协议的连接情况
- -u 显示udp传输协议的连接状况
- -l 表示listening,显示正在监听状态的服务,也可以用-a表示所有状态
- -n: 表示numeric,用数字形式显示端口号
- -p:表示process 表示显示后台进程
常用组合: neststat -lntp
Linux下查看负载情况?
平均负载,是指处于运行或不可打扰状态的进程的平均数。(主要是R和D状态的进程)
在 Linux 系统中,要查看负载情况一般使用 uptime 命令(w 命令和 top 命令也行)*
$ uptime
16:33:56 up 69 days, 5:10, 1 user, load average: 0.14, 0.24, 0.29
以上信息的解析如下:
-
16:33:56 : 当前时间
-
up 69 days, 5:10 : 系统运行了 69 天 5 小时 10 分
-
1 user : 当前有 1 个用户登录了系统
-
load average: 0.14, 0.24, 0.29 : 系统在过去 1 分钟内,5 分钟内,15 分钟内的平均负载
平均负载一般小于你的cpu总核心数就是正常的,说明有空闲的cpu。
linux:统计一个文件里指定关键字的出现的次数
grep -wo 'hello' file.txt | wc -l
其中,“-w”选项可以确保只匹配完整的单词,“-o”选项可以让grep命令只输出匹配到的单词,“wc -l”命令可以统计行数,也就是匹配到的单词出现的次数
如何把客户机的公钥添加到服务器的列表中(SSH)
目的 避免重复输入用户密码,通过SSH自动登录,节约时间
在Linux系统中,可以使用ssh命令将客户机的公钥添加到服务器的authorized_keys文件中,实现无需密码登录。具体步骤如下:
- 在客户机上生成公钥和私钥,如果已经生成过可以跳过这一步骤。使用ssh-keygen命令生成公钥和私钥,例如:
ssh-keygen
该命令会在用户的家目录下生成公钥文件(id_rsa.pub)和私钥文件(id_rsa)。
- 将客户机的公钥添加到服务器的authorized_keys文件中。将公钥文件内容复制到剪贴板中,然后使用ssh命令将公钥添加到服务器的authorized_keys文件中。例如,假设客户机的公钥文件为“id_rsa.pub”,服务器的IP地址为“192.168.0.1”,用户名为“username”,可以输入以下命令:
ssh-copy-id -i ~/.ssh/id_rsa.pub username@192.168.0.1
在这个命令中,“-i”选项用来指定公钥文件路径,“username”是服务器的用户名,“192.168.0.1”是服务器的IP地址。
- 输入服务器的登录密码。如果之前没有将客户机的公钥添加到服务器的authorized_keys文件中,会提示输入服务器的登录密码。输入密码后,客户机的公钥会被添加到服务器的authorized_keys文件中。
- 完成添加。添加成功后,可以使用ssh命令无需密码登录服务器。例如,输入以下命令即可登录服务器:
ssh username@192.168.0.1
在这个命令中,“username”是服务器的用户名,“192.168.0.1”是服务器的IP地址。
VIM(替换,删除等指令)
简单描述一些常见的方式:
替换命令:
- :s/old/new/g:将当前行中所有的“old”替换成“new”。其中,g表示全局替换,如果不加g,则只会替换当前行中第一个匹配到的“old”。
- :%s/old/new/g:将整个文档中所有的“old”替换成“new”。
删除命令:
- x:删除光标所在位置的字符。
- dd:删除当前行。
Linux解压文件操作
打包文件
将一个或多个文件或目录打包为单个tar文件:
tar -czvf archive.tar.gz /path/to/file1 /path/to/file2 /path/to/dir1
-c
:表示创建一个新的tar文件。-z
:表示使用gzip进行压缩。-v
:表示输出详细信息,可以看到打包过程中的每个文件。-f
:表示指定输出的文件名,后面紧跟要打包的文件和目录。
解压文件
将tar文件解压到指定的目录:
tar -xzvf archive.tar.gz -C /path/to/destination
-x
:表示解压缩一个已经存在的tar文件。-z
:表示使用gzip进行解压缩。-v
:表示输出详细信息,可以看到解压缩过程中的每个文件。-f
:表示指定要解压的tar文件名,后面紧跟要解压缩到的目录。-C
:表示指定解压缩到的目录。
100行5列的文件每列用空格隔开计算第三列数字的和
awk '{sum+=$3} END {print sum}' filename.txt
Linux命令,查看8080端口的进程
lsof -i :8080
使用 lsof
命令可以查看哪些进程正在使用特定的文件或者网络端口
linux系统下常用的监控命令?
我是常用top命令,所以简单介绍一下top吧。
top命令可以帮我们全面了解cpu,内存,进程等一系列当前服务的状态。
在top命令的输出中,可以看到以下信息:
- 第一行:系统当前时间、运行时间、登录用户数、系统负载。
- 第二行:总进程数、运行中进程数、睡眠中进程数、停止进程数、僵尸进程数。
- 第三行:CPU使用情况,包括用户态、系统态、空闲和等待IO的CPU占用百分比。
- 第四行:内存使用情况,包括物理内存总量、空闲内存、已用内存、缓存和缓存已用内存。
- 第五行:交换分区使用情况,包括总交换分区、空闲交换分区和已用交换分区。
- 进程信息:进程的PID、用户、CPU占用、内存占用、进程状态、启动时间、进程命令等。
当我们创建一个linux用户的用户密码存放在哪个文件目录?
在Linux中,用户密码不是明文存储的,而是经过加密处理后存储在系统中。具体来说,密码是以加密方式存储在系统的/etc/shadow文件中。
该文件只有root用户有读写权限,其他用户不能访问该文件。这样可以保护用户密码不被其他用户访问或泄露。
在/etc/shadow文件中,每个用户的密码信息占用一行,包括用户名、加密后的密码、最后一次修改密码的日期、密码过期时间等信息。用户密码的加密方式通常采用哈希(hash)算法,如MD5、SHA等。
查看权限命令
一般都是用ls -l
: 显示当前目录下的所有文件和目录的详细信息,包括文件权限、所有者、所属组、文件大小、创建日期等信息
Linux IO有哪些方式
总共有5种IO方式
五种I/O模型:
- 同步阻塞型、同步非阻塞型、IO多路复用型、信号驱动I/O型、异步I/O型
阻塞式I/O模型(Blocking I/O Model)
同步阻塞IO模型是最简单的IO模型,用户线程在内核进行IO操作时被阻塞
非阻塞式I/O模型(Non-Blocking I/O Model)
在这种I/O模型中,当应用程序执行一个I/O操作时,它不会一直等待,而是立即返回,不管I/O操作是否完成。
用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。即“轮询”机制
I/O复用模型(I/O Multiplexing Model)
简单来说,上面非阻塞I/O会轮训问好没好,那如果请求有几百万个,是不是同时有几百万个线程人问,这样是对资源的巨大浪费。
为了解决这个问题,我们使用中介者模式,让一个线程作为代理,它去轮训问几百万个接口,应用程序可以在一个线程中等待多个I/O操作完成,从而减少线程数量和系统开销。 当一个I/O操作完成时,应用程序会被通知并处理完成的I/O操作。
信号驱动I/O模型(Signal Driven I/O Model)
但是上面的I/O复用模型仍然有一个线程要去轮训,有没有办法不轮询? 在这种I/O模型中,当应用程序执行一个I/O操作时,它会立即返回,并注册一个信号处理函数。当I/O操作完成时,内核会发送一个信号给应用程序,通知它I/O操作已完成。应用程序可以在信号处理函数中处理完成的I/O操作。
异步I/O模型(Asynchronous I/O Model)
在这种I/O模型中,当应用程序执行一个I/O操作时,它会立即返回,并注册一个回调函数。当I/O操作完成时,内核会调用回调函数,并传递完成的I/O操作的结果。应用程序可以在回调函数中处理完成的I/O操作。
用户程序写4KB的数据,写到磁盘上,经历的过程
- 用户程序将数据写入文件,通过系统调用将数据传递给操作系统内核。
- 上图可以看到,写文件首先是借助虚拟文件系统去往缓冲区写数据的,虚拟文件系统屏蔽了各种具体的文件系统,提供了统一的调用方式。
- 操作系统内核将数据存储到系统内核缓存(buffer cache)中,等待写入磁盘。缓存是操作系统用来暂存文件系统的数据和元数据的内存区域。当应用程序向磁盘写入数据时,这些数据首先被写入到内核缓存中,再由内核异步写入磁盘。
- 当磁盘控制器将数据从磁盘缓存区写入磁盘后,会向操作系统内核发送一个中断信号(interrupt),表示数据已经成功写入磁盘。此时,操作系统内核会将文件系统的元数据更新,包括文件大小、修改时间等。
下面是一些基础的问题,可以看看这篇文章,我看内容还可以,但我不知道这篇文章是否是真题
转载自:https://juejin.cn/post/7211467514413203511