Linux basic

Last updated on 3 months ago

关机重启

1
2
3
4
5
6
shutdown -h now //立刻关机
shutdown -h 1 //1 分钟后关机
shutdown -r now //现在重启
halt //关机,与上面一样
reboot //现在重启,与上面一样
sync //将内存的数据同步到磁盘

用户登录和注销

登录

一般最好不要用 root 登录,因为这东西的权限最大。为避免操作失误,尽量少用。

登录的时候可以用普通用户登录,然后再用

1
2
su - 用户名
//例如 su - root

命令来切换成系统管理员身份

注销

相应地,可以用

1
logout

来注销用户

需要说明的是,这个命令不能在图像界面使用。并且在最后一个用户的时候使用的话会直接退出系统

用户管理

添加用户

1
useradd 用户名

这一条指令会自动在 home 目录下面创建默认的家目录

家目录的文件名默认为用户名称,如果需要进行更改,可以输入:

1
useradd -d 文件名 用户名

在 Ubuntu 下直接用这一个命令只会创建用户而不会创建家目录,需要写:

1
useradd -m 用户名

相应的,我们可以修改用户密码:

1
passwd 用户名

如果不在后面加用户名的话,会默认修改当前用户的密码

删除用户

1
userdel 用户名

上面这个是基本指令,但实际上的删除用户有两种情况:

  • 保留家目录
  • 不保留家目录

对于前者,我们直接输入

1
userdel 用户名

就行,这个是默认保留家目录

对于后者,我们需要输入

1
userdel -r 用户名

这样就会将家目录一起删除

查询用户

1
id 用户名

切换用户

1
su - 用户名

从权限高的用户切换到权限低的用户,不需要输入密码,反之需要

如果需要返回原来的用户,可以输入

1
2
3
exit
//或者
logout

查看当前用户信息

如果需要查看目前正在登录的用户信息,可以输入

1
2
3
whoami
//或者
who am i

用户组

在 Linux 中,如果多个用户拥有相同的权限,除了一个一个设置权限外还有一种方法是:将所以的用户拉到一个组,对这个组赋予权限

因此我们说,用户组的作用是允许系统对有相同权限的多个用户进行统一管理

创建组

一般的命令是这个:

1
groupadd 组名

当然,我们也给定一个参数来指明这个组的 group id ,即:

1
groupadd -g 组id 组名

删除组

1
groupdel 组名

将用户添加到组

我们可以在添加一个用户的时候直接将其加入到一个组里面,即:

1
useradd -g 用户组 用户名

需要说明的是,如果在添加用户的时候没有指定组,那么会默认创建一个与该用户名相同的组

修改用户的组

我们可以将一个用户的组进行修改,即:

1
usermod -g 用户组 用户名

用户和组的相关文件

  • /etc/passwd 文件

用户( user )的配置文件,记录用户的各种信息

每行含义:用户 :口令 :用户标识号 :组标识号 :注释性描述 :主目录 :登陆Shell

解释:

  1. 口令一般加密,只会显示 X
  2. 用户标识号是用户的 uid
  3. 组标识号是组的 uid
  4. Shell 可以理解成一个将控制台指令翻译成 Linux 内核可以理解的代码的工具,一般使用 bash
  • /etc/shadow 文件

用户口令的配置文件(这东西看不懂的)

每行含义:登录名 :加密口令 :最后一次修改时间 :最小时间间隔 :警告时间 :不活动时间 :失效时间 :标志

说明:

  1. 这里的加密口令是加密过的,如果没有设置密码的话这里为空
  2. 后面的部分全部都是一些特殊的数字,看不懂
  • /etc/group 文件

组的配置文件,记录 Linux 包含的组的信息

每行含义:组名 :口令 :组标识号 :组内用户列表

说明:

  1. 那个组内用户列表是看不到的,被隐藏起来了

运行级别

说明

运行级别说明:

0 :关机

1 :单用户(可以用于找回丢失的密码)

2 :多用户状态但没有网络服务(几乎不用)

3 :多用户状态有网络服务(用的最多)

4 :系统未使用保留给用户(这个没用)

5 :图形界面(用的最多)

6 :系统重启,默认运行级别不能是 6 ,否则系统无法正常启动

常用的运行级别是 3 和 5 ,当然也可以制定默认运行级别

查看默认运行级别

1
systemctl get-default 运行级别

这里需要说明的是:

multi-user.target 相当于运行级别 3 ,也就是多用户有网络服务

graphical.target 相当于运行级别 5 ,即图形化界面

还有就是,后面那个运行级别需要写英文,不能写数字

帮助指令

  • man 获得帮助信息
1
man 命令或配置文件

举个例子,我们需要查看 ls 命令的帮助信息,可以用

1
man ls

补充:Linux 下以 . 开头的文件表示隐藏文件

  • help 命令

这个可以用于获取 shell 内置命令的帮助信息

文件目录指令

pwd 指令

1
pwd

显示当前工作目录的绝对路径

ls 指令

1
ls

列出当前目录下的文件信息

参数:

-a :显示当前目录的所有文件和目录,包括隐藏的

-l :以列表的方式显示信息

cd 指令

1
cd 目录

切换到指定目录

cd ~ 或者 cd 这两个都是回到自己的家目录。比如,如果是 root 用户,则会回到 root 的家目录 /root

cd.. 回到当前目录的上一级目录

mkdir 指令

实际上是 make directory创建目录的意思,不是创建文件

1
mkdir [选项] 要创建的目录

常用选项:

-p :创建多级目录

mkdir 默认只能创建一级目录,需要创建多级的话需要加参数

还有一个就是这东西如果只写目录名的话那么默认在当前目录下创建目录

rmdir 指令

remove directory ,删除空目录。这个指令只能删除空目录,如果目录当中有内容则不能用

1
rmdir [选项] 目录名

如果要删除非空目录,则用 rm -rf 目录名 。后面的 r 代表 recursion ,递归的;f 代表 force ,强制的

touch 指令

创建空文件,啥都不写的那种

touch 是创建文件,mkdir 是创建目录

1
touch 文件名

比如,可以写 touch main.cpp 这种

cp 指令

copy 的意思,拷贝文件到指定目录

1
cp [选项] source destination

-r 递归地拷贝整个目录

这个指令默认是拷贝文件,如果是想要拷贝目录的话需要加上 -r

需要说明的是,在复制的时候会提示是否去覆盖原文件。如果文件很多的话一个一个确认会很麻烦,因此我们可以输入一个强制覆盖的指令:

1
\cp -r source destination

这样的话就不会有提示了

rm 指令

可以用于移除文件或目录

1
rm [选项] 要删除的文件或目录

选项:

-r :递归删除整个文件夹

-f :强制删除不提示

注意,如果是删文件的话就不要带参数

mv 指令

移动文件与目录或者重命名

1
2
mv oldName newName //重命名
mv source destination //移动文件

这个指令可以移动文件重命名。实际上,对于重命名的情况,只要 oldNamenewName 处于同一个目录下就是重命名,否则就是移动文件

cat 指令

查看文件内容,这个指令是只能查看不能修改,而 vim 指令则是既可以查看也可以修改。因此 cat 相比于 vim 更安全

1
cat [选项] 要查看的文件

常用选项:

-n :显示行号

管道命令:将前一个命令的结果交给后一个命令进行处理

cat 指令是可以跟管道命令一起使用的,如下:

1
cat -n 文件名 | more

more 其实是一个指令,并不是一个参赛

more 指令

1
more 要查看的文件

more 指令是一个基于 vi 编辑器的文本过滤器,它以全屏的形式显示文本文件的内容

操作 功能
空格 向下翻页
Enter 向下一行
q 退出
Ctrl + F 向下滚动一屏
Ctrl + B 返回上一屏
= 输出当前行号
:f 输出文件名和当前行号

less 指令

less 的功能与 more 类似,但功能相比于 more 更加强大。

vim 用来查看文件是会将整个文件全部加载到内存当中,less 只会加载需要查看的部分,是一种动态加载。

操作 功能
空格 向下翻页
PageDown 向下翻页
PageUp 向上翻页
/ 字符串 查找;n 向下查找,N 向上查找
? 字符串 查找,方式与上面的相反
q 退出

echo 指令

输出内容到控制台

1
echo [选项] [输出内容]

例如我们可以输出环境变量 $HOSTNAME 到控制台,即 echo $HOSTNAME

或者直接输出 Hello World ,即 echo "Hello World"

head 指令

用于显示文件开头部分内容,默认情况下是显示前 10 行的内容

1
2
head 文件
head -n 5 文件 //显示 5 行,可以是任意数

tail 指令

用于显示文件末尾部分内容,默认是最后 10 行的内容

1
2
3
tail 文件
tail -n 5 文件 //显示最后 5 行,可以是任意数
tail -f 文件 //实时追踪该文档的所有更新

第三条指令会占用终端来实时监控该文件的更新

> 指令和 >> 指令

> 是输出重定向,就是将原来输出的地方重定向到另外一个地方

>>> 唯一的区别是,前者会先将原文件的内容全部清空,然后在输入,也就是覆盖写入;后者是在原文件末尾进行追加,并不会覆盖

例如,我们可以 ls -l > 文件名 或者 ls -l >> 文件名

需要注意的是,cat 文件1 > 文件2 这相当于是将文件1的内容覆盖到文件2当中去。

要理解的话很简单,cat 指令是显示文件内容,然后用 > 重定向到另一个文件,就相当于是用第二个文件来显示第一个文件的内容,并且是覆盖写入,所以就是将文件1覆盖文件2

ln 指令

创建一个软链接,就相当于 win 里面的快捷方式

1
ln -s 原文件或目录 软链接名

需要注意的是,使用 pwd 查看软连接文件路径时,会显示软连接文件的路径不会显示原文件的路径

history 指令

查看已经执行过的历史命令,也可以执行历史命令

1
2
3
history     //查询所有的历史命令
hestory 10 //显示最近执行的 10 条命令
!10 //执行历史编号为 10 的命令

时间日期指令

这个很简单,我们直接过一下就行

date 指令

用于查看时间

1
2
date    //显示所有
date "+%Y %m %d %H %M %S" //这里的参数可以自定义,但 + 一定要有

date 还可以用于设置日期

1
date -s 字符串时间

例如,可以写 date -s "2022-9-2 10:02:30"

cal 指令

用于查看日历

1
cal [选项]

不加 选项 ,显示本月月历,加了之后可以显示那一年整年的日历

搜索查找

find 指令

从指定目录向下递归遍历各个子目录,将满足条件的文件或目录显示在终端

1
find [搜索文件] [选项]

选项说明:

选项 功能
-name 文件名 按指定文件名查找文件
-user 用户名 查找属于指定用户名所有的文件
-size 大小 按文件大小进行查询,+ 表示大于,- 表示小于,单位有 K, M, G
1
2
find / +200M  //在根目录下查找大约 200M 的文件
find / 200M //在根目录下查找等于 200M 的文件

locate 指令

locate 可以快速定位文件路径,因为这是基于数据库进行的查找,不需要遍历整个文件系统。为了保证查询结果的准确度,管理员必须定期更新 locate 时刻

1
locate 搜索文件

需要注意的是,由于 locate 指令基于数据库查询,所以在第一次运行前,需要执行 updatedb

which 指令

可以查看某个指令在哪个目录下,具体用法为:

1
which 指令

例如,which ls 就是查询 ls 指令所在的目录

grep 指令

grep 是过滤查找,也就是按照关键字查找的意思,通常会跟管道命令 | 结合起来使用

1
grep [选项] 查找内容 查找文件

选项:

选项 功能
-n 显示行号
-i 忽略字母大小写

例如,我们可以写 cat 文件名 | grep -n 查找关键字 ,查找关键字需要用字符串

相应地,我也可以直接 grep -n 查找关键字 文件名

文件压缩和解压

gzip 和 gunzip 指令

gzip 用于压缩文件,压缩后文件的后缀只能.gz

gunzip 用于解压文件,解压后缀为 .gz 的文件

1
2
gzip 文件      //得到 文件.gz
gunzip 文件.gz //得到 文件

zip 和 unzip 指令

zip 用于压缩文件或目录unzip 用于解压

上面的 gzip 只能用于压缩文件,目录是不能压缩的

1
2
zip [选项] 压缩文件名.zip 待压缩文件
unzip [选项] 压缩文件名.zip

zip 常用选项:

-r :递归地进行压缩,用于压缩目录

unzip 常用选项

-d :指定解压后文件存放的目录

tar 指令

tar 既可以用于压缩也可以用于解压,其对象既可以是文件也可以是目录,最后打包得到的是 文件名.tar.gz 文件

至于如何确定是压缩还是解压,通过选项来确定

1
tar [选项] xxx.tar.gz 待打包文件
选项 功能
-c 产生 .tar 打包文件
-v 显示详细信息
-f 指定压缩后的文件名
-z 打包同时压缩
-x 解包

压缩文件可以写:

1
tar -zcvf xxx.tar.gz 待压缩文件

后面可以写多个文件

解压可以写:

1
tar -zxvf xxx.tar.gz

解压到指定目录:

1
tar -zxvf xxx.tar.gz -C 目录名

组管理和权限管理

Linux 中,每个用户都会所在一个组,反过来,组可以更方便地管理用户

Linux 中的每个文件均有三个概念:所有者,所在组,其他组

  • 所有者是指该文件的创建用户是谁
  • 所在组是指该文件的创建用户所在的组
  • 其他组是指除了该文件所在的组以外的其他组

chown 指令

change own 改变所有者,该指令可以修改一个文件或目录的所有者

1
chown 所有者 文件名

当然也可以同时更改一个文件或目录的所有者和所在组

1
chown 所有者:所在组 文件名

例如:chown chisato:chisato test

如果需要对整个目录的所有者或所在组进行修改的话,可以加 -R 选项来让操作递归下去

1
chown -R 所有者 文件名

chgrp 指令

change group 修改所在组,该指令可以修改一个文件或目录的所在组

1
chgrp 组名 文件名

如果需要更改一个目录当中的所有的文件,可以加上 -R 参数,即:

1
chgrp -R 组名 目录名

修改用户所在组

在添加用户时,我们可以指定用户所在组,即:

1
useradd -g 组名 用户名

除此之外,我们可以用 root 权限更改某个用户所在组

1
usermod -g 新组名 用户名

除此之外,usermod 还可以修改用户的初始登录目录,即:

1
usermod -d 目录名 用户名

需要注意的是,用户必须要有能够进入该目录的权限,否则会修改失败

权限

ls -l 指令显示内容后,第一列(一共 10 个字母)表示该文件或目录的权限

0 - 9 位的详细说明:

  1. 第 0 位表示文件类型

    • l 是链接,对应 windows 里的快捷方式

    • d 是目录,也就是文件夹

    • c 是字符设备文件、鼠标、键盘

    • b 是块设备,比如硬盘

    • - 表示该文件就是一个普通文件

  2. 第 1 - 3 位为该文件所有者对该文件的权限

  3. 第 4 - 6 位为该文件所在组中的用户对该文件的权限

  4. 第 7 - 9 位为该文件其他组中的用户对该文件的权限

第 1 - 9 位均是描述权限,权限有三种:rwx

r 表示 read ,可读

w 表示 write ,可写

x 表示 execute ,可执行

rwx 作用到文件与作用到目录是不一样的,具体如下:

  • rwx 作用到文件
    • r 表示可读:允许对该文件进行读取、查看
    • w 表示可写:允许对该文件进行修改,但不能删除。如果要删除文件需要对该文件所在的目录有 w 的权限
    • e 表示可执行:允许该文件被执行
  • rwx 作用到目录
    • r 表示可读:允许读取、查看该目录的内容
    • w 表示可写:允许对该目录内的文件进行创建、删除的操作,还允许对该目录进行重命名
    • x 表是可执行:允许用户进入到这个目录。如果没有 x 权限则用户无法进入该目录

Linux 中还可以用数字来表示权限,如:r = 4w = 2x = 1 ,因此 rwx = 7

chmod 指令

通过 chmod 指令,可以修改文件或者目录的权限

1
chmod [选项] 文件名

有两种方式可以对权限进行修改

  • +-= 进行修改
    • u 表示 user ,即该文件的所有者
    • g 表示 group ,即该文件的所在组
    • o 表示 other ,即该文件的其他组
    • a 表示 all ,即全部
    • + 表示添加该权限,- 表示去掉该权限,= 就是直接赋值

例如:

对所有者赋予 rwx ,所在组赋予 rw ,其他组赋予 x

1
chmod u=rwx,g=rw,o=x 文件名

对所有人去除 x

1
chmod a-x 文件名

这里的各个参数之间是不允许打空格的

  • 用数字变更权限
    • r 用 4 表示,w 用 2 表示,x 用 1 表示
    • 可以通过数字的加法来实现权限的更改

对所有者赋予 rwx ,所在组赋予 rw ,其他组赋予 x

1
chmod 761 文件名

同样不能打空格

关于目录的 rwx 的讨论

x 表示可以进入到该目录,可以执行 cd

r 表示可以读取该目录的文件,可以执行 ls

w 表示可以对该目录当中的文件进行增加或修改

crond 任务调度

如果我们希望系统自动定时帮我们去做一些任务,可以通过 crontab 进行定时任务设置

任务调度:指系统在某个时间执行特点的命令或程序

任务调度分为系统工作和个别用户工作,前者是指某些工作必须要周而复始地执行,例如病毒扫描;后者是指个别用户希望执行某些程序,例如数据库备份

crontab 指令

1
crontab [选项]

常用选项:

-e :编辑 crontab 定时任务

-l :查询 crontab 任务

-r :删除当前用户所有 crontab 任务

这里关于时间的设置我们需要重点记一下

一般我们会这么写:

1
2
crontab -e
* * * * * ls -l /home/ > /home/log.txt

后面是一个重定向,我们重点看前面那 5 个 *

第一个 * ,表示一小时当中的第几分钟

第二个 * ,表示一天当中的第几小时

第三个 * ,表示一个月当中的第几天

第四个 * ,表示一年当中的第几月

第五个 * ,表示一周当中的星期几,范围:0 - 7(0 与 7 均表示星期天)

特殊符号说明:

* 表示任何时间

, 表示不连续的时间

- 表示时间范围

*/n 表示多久执行一次

硬盘分区

Linux 的文件系统中,最上层的是一个根目录,其他目录是在根目录之下可以通过根目录来进行访问的存在。但这仅仅是文件系统的结构,我们还需要将硬盘的存储空间与每个目录之间联系起来

Linux 采用了一种称为『载入』的处理办法。硬盘当中可以对空间进行划分,得到一个一个分区,Linux 可以将分区直接『挂载』到对应的目录下,这样便可以通过目录来访问对应的硬盘空间了

硬盘说明

Linux 分 IDE 硬盘和 SCSI 硬盘,目前基本上都是后者

对于 IDE 硬盘,标识符为 hdx~ ;对于 SCSI 硬盘,标识符为 sdx~

这里我们介绍 SCSI ,IDE 同理

  • sd 用来表示分区所在设备的类型(指 SCSI 硬盘)
  • x 为盘号(a 为基本盘,b为基本从属盘,c 为辅助主盘,d 为辅助从属盘)
  • ~ 表示分区,前四个分区用数字 1 到 4 表示,它们表示主分区或拓展分区,从第 5 开始是逻辑分区

lsblk 指令

我们可以用 lsblk 或者 lsblk -l 来查看分区情况,即:

1
2
lsblk
lsblk -l

df -h 指令

查询系统整体硬盘使用情况

1
df -h

当分区使用率到达百分之八十以上,需要去删除文件或者拓展分区

du -h 指令

用于查询指定目录的硬盘占用情况,默认为当前目录

1
du [选项] 目录名

常用选项:

  • -s :指定目录占用大小汇总
  • -h :带计量单位
  • -a :含文件
  • --max-depth= :子目录列举深度,建议写 1
  • -c :列出明细的同时,增加汇总值

磁盘查询常用指令

统计 /home 目录下文件的个数:

1
ls -l | grep "^-" | wc -l

统计 /home 目录下文件夹的个数:

1
ls -l | grep "^d" | wc -l

统计 /home 目录下的文件个数,包括子文件夹内的

1
ls -Rl | grep "^-" | wc -l

ls 那里的 R 表示递归列举

进程

在 Linux 中,每个执行的程序都被称为一个进程,每个进程都会有一个 PID

进程的可能以两种方式进行存在:前台和后台

前台程序就是目前用户在屏幕上自己操作的,后台进程是屏幕上无法看到但实际在运行的

一般系统服务会以后台的形式常住在系统中,直到关机才结束

ps 指令

ps 指令是用于查看目前系统中,有哪些正在执行,以及它们执行的状况。可以不加参数执行

1
ps [选项]

-a :显示当前终端所有进程信息

-u :以用户的格式显示进程信息

-x :显示后台进程运行的参数

-e :显示所有进程

-f :全格式

指令说明:

USER :用户名称

PID :进程号

%CPU :进程占用 CPU 的百分比

%MEM :进程占用物理内存的百分比

VSZ :进程占用虚拟内存的大小

RSS :进程占用物理内存的大小

TTY :终端名称

STAT :进程状态

  • S 睡眠,s 表示该进程三会话的先导进程
  • N 表示进程拥有比普通优先级更低的优先级
  • R 正在运行
  • D 短期等待
  • Z 僵死进程
  • T 被跟踪或者被停止

kill 和 killall 指令

killkillall 均可以用来终止进程,基本语法为:

1
2
kill [选项] 进程号
killall 进程名称

killall 会终止掉一个进程及其所有子进程,kill 只会终止调当前进程

有的时候,kill 作用在某些进程上会失效,原因在于 Linux 系统认为这是重要的进程,会自动忽略调该指令。如果需要强制停止可以加上 -9 这个选项

pstree 指令

以树的形式显示进程信息,看的更加直观

1
pstree [选项]

常用选项:

-p :显示进程的 PID

-u :显示进程的所属用户

服务

服务的本质就是进程,通常是在后台运行,来监听某个端口等待其他程序的请求(比如:mysqld, sshd, 防火墙),因此我们也称服务为守护进程

service 指令

我们可以用 service 指令来管理服务,指令如下:

1
service 服务名 [start | stop | restart | reload | status]

我们可以在 /etc/init.d 当中查看 service 管理的服务名称,即:

1
ls -l /etc/init.d/

开机流程说明:

开机 >> BIOS >> /boot >> systemd进程 1 >> 运行级别 >> 运行级别对应的服务

chkconfig 指令

全部是 check config ,用于设置服务在各个运行级别的自启动或者不自启动

基本语法:

1
chkconfig --list  //查看服务

修改某个服务在 5 运行级别下的自启动

1
chkconfig --level 5 服务名 on/off

chkconfig 设置完毕后需要重启机器才能生效

需要注意的是,这个指令在 Ubuntu 下使用不了

systemctl 指令

该指令管理的服务在 /usr/lib/systemd/system 查看

管理服务指令:

1
systemctl [start | stop | restart | status]

查看服务开机启动状态

1
systemctl list-unit-files

设置服务开机自启动

1
systemctl enable 服务名

关闭服务开机启动

1
systemctl disable 服务名

查询某个服务是否自启动

1
systemctl is-enable 服务名

Shell 编程

Shell 是一个命令行解释器,它介于外层应用程序和 Linux 内核之间。它为用户提供了一个向 Linux 内核发送请求以便运行程序的界面系统级程序

  • 脚本格式要求

脚本需要以 #!/bin/bash 开头

脚本需要有可执行权限

shell 脚本一般以 .sh 来结尾

  • 执行方式

输入绝对路径或相对路径(需要有执行权限)

sh + 脚本(不需要执行权限)

Shell 变量

Linux 当中的 Shell 变量分为系统变量和用户自定义变量

系统变量为:$HOME, $PWD, $SHELL, $USER 等

可以用 set 来显示当前 Shell 当中的所有变量

定义变量:变量名=值(不能加空格)

撤销变量:unset 变量

声明静态变量:readonly 变量,静态变量不能 unset

变量名一般习惯大写

Shell 里面的变量没有类型之分,因此可以将指令的结果赋值给变量,具体操作为:A='date' 或者 A=$(date) 需要用反引号或在 $ 来指明,否则系统会认为这是一个字符串

设置环境变量

/etc/profile 文件中添加 export 变量名=变量值

之后用 source /etc/profile 更新一下文件,这样便新建了一个环境变量

这个环境变量可以在所有的 Shell 脚本当中使用

Shell 脚本当中的多行注释的写法

1
2
3
:<<!
内容
!

位置参数变量

在我们用命令行执行 Shell 脚本时,可以向里面传入参数,这个参数也就是位置参数,基本语法如下:

$nn 为数字,$1-9 表示第一到第九个参数,十以上的参数需要用 ${10} 这样表示

$* :拿到命令行当中的所有参数,会将所有传入的参数当成一个整体

$@ :同样也是拿到所有参数,不过会将每个参数区分对待

$# :表示命令行当中参数的个数


Linux basic
https://nishikichisato.github.io/2022/09/17/Linux/Linux-basic/
Author
Nishiki Chisato
Posted on
September 17, 2022
Updated on
November 25, 2023
Licensed under