乙巳🐍年

acc8226 的博客

Linux 中也难免遇到某个程序无响应的情况,可以通过一些命令来帮助我们让系统能够更流畅的运行。 而在此之前,我们需要对进程的基础知识有一定的了解,才能更好、更有效率的使用 Linux 提供的工具。

进程与程序

首先程序与进程是什么?程序与进程又有什么区别?

程序(procedure):不太精确地说,程序就是执行一系列有逻辑、有顺序结构的指令,帮我们达成某个结果。就如我们去餐馆,给服务员说我要牛肉盖浇饭,她执行了做牛肉盖浇饭这么一个程序,最后我们得到了这么一盘牛肉盖浇饭。它需要去执行,不然它就像一本武功秘籍,放在那里等人翻看。
进程(process):进程是程序在一个数据集合上的一次执行过程,在早期的 UNIX、Linux 2.4 及更早的版本中,它是系统进行资源分配和调度的独立基本单位。同上一个例子,就如我们去了餐馆,给服务员说我要牛肉盖浇饭,她执行了做牛肉盖浇饭这么一个程序,而里面做饭的是一个进程,做牛肉汤汁的是一个进程,把牛肉汤汁与饭混合在一起的是一个进程,把饭端上桌的是一个进程。它就像是我们在看武功秘籍这么一个过程,然后一个篇章一个篇章地去练。

简单来说,程序是为了完成某种任务而设计的软件,比如 vim 是程序。什么是进程呢?进程就是运行中的程序。

程序只是一些列指令的集合,是一个静止的实体,而进程不同,进程有以下的特性:

  • 动态性:进程的实质是一次程序执行的过程,有创建、撤销等状态的变化。而程序是一个静态的实体。
  • 并发性:进程可以做到在一个时间段内,有多个程序在运行中。程序只是静态的实体,所以不存在并发性。
  • 独立性:进程可以独立分配资源,独立接受调度,独立地运行。
  • 异步性:进程以不可预知的速度向前推进。
  • 结构性:进程拥有代码段、数据段、PCB(进程控制块,进程存在的唯一标志)。也正是因为有结构性,进程才可以做到独立地运行。

**并发:**在一个时间段内,宏观来看有多个程序都在活动,有条不紊的执行(每一瞬间只有一个在执行,只是在一段时间有多个程序都执行过)
**并行:**在每一个瞬间,都有多个程序都在同时执行,这个必须有多个 CPU 才行

引入进程是因为传统意义上的程序已经不足以描述 OS 中各种活动之间的动态性、并发性、独立性还有相互制约性。程序就像一个公司,只是一些证书,文件的堆积(静态实体)。而当公司运作起来就有各个部门的区分,财务部,技术部,销售部等等,就像各个进程,各个部门之间可以独立运做,也可以有交互(独立性、并发性)。

而随着程序的发展越做越大,又会继续细分,从而引入了线程的概念,当代多数操作系统、Linux 2.6 及更新的版本中,进程本身不是基本运行单位,而是线程的容器。就像上述所说的,每个部门又会细分为各个工作小组(线程),而工作小组需要的资源需要向上级(进程)申请。

线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。因为线程中几乎不包含系统资源,所以执行更快、更有效率。

简而言之,一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。就如下图所示:

进程的分类

大概明白进程是个什么样的存在后,我们需要进一步了解的就是进程分类。可以从两个角度来分:

以进程的功能与服务的对象来分;
以应用程序的服务类型来分;

第一个角度来看,我们可以分为用户进程与系统进程:

用户进程:通过执行用户程序、应用程序或称之为内核之外的系统程序而产生的进程,此类进程可以在用户的控制下运行或关闭。
系统进程:通过执行系统内核程序而产生的进程,比如可以执行内存资源分配和进程切换等相对底层的工作;而且该进程的运行不受用户的干预,即使是 root 用户也不能干预系统进程的运行。

第二角度来看,我们可以将进程分为交互进程、批处理进程、守护进程

交互进程:由一个 shell 终端启动的进程,在执行过程中,需要与用户进行交互操作,可以运行于前台,也可以运行在后台。
批处理进程:该进程是一个进程集合,负责按顺序启动其他的进程。
守护进程:守护进程是一直运行的一种进程,在 Linux 系统启动时启动,在系统关闭时终止。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。例如 httpd 进程,一直处于运行状态,等待用户的访问。还有经常用的 cron(在 centOS 系列为 crond)进程,这个进程为 crontab 的守护进程,可以周期性的执行用户设定的某些任务。

进程的衍生

进程有这么多的种类,那么进程之间定是有相关性的,而这些有关联性的进程又是如何产生的,如何衍生的?

就比如我们启动了终端,就是启动了一个 bash 进程,我们可以在 bash 中再输入 bash 则会再启动一个 bash 的进程,此时第二个 bash 进程就是由第一个 bash 进程创建出来的,他们之间又是个什么关系?

我们一般称呼第一个 bash 进程是第二 bash 进程的父进程,第二 bash 进程是第一个 bash 进程的子进程,这层关系是如何得来的呢?

关于父进程与子进程便会提及这两个系统调用 fork() 与 exec()

fork-exec是由 Dennis M. Ritchie 创造的
fork() 是一个系统调用(system call),它的主要作用就是为当前的进程创建一个新的进程,这个新的进程就是它的子进程,这个子进程除了父进程的返回值和 PID 以外其他的都一模一样,如进程的执行代码段,内存信息,文件描述,寄存器状态等等
exec() 也是系统调用,作用是切换子进程中的执行程序也就是替换其从父进程复制过来的代码段与数据段

子进程就是父进程通过系统调用 fork() 而产生的复制品,fork() 就是把父进程的 PCB 等进程的数据结构信息直接复制过来,只是修改了 PID,所以一模一样,只有在执行 exec() 之后才会不同,而早先的 fork() 比较消耗资源后来进化成 vfork(),效率高了不少,感兴趣的同学可以查查为什么。

这就是子进程产生的由来。简单的实现逻辑就如下方所示【注释1】

1
2
3
4
5
6
7
8
9
pid_t p;

p = fork();
if (p == (pid_t) -1)
/* ERROR */
else if (p == 0)
/* CHILD */
else
/* PARENT */

既然子进程是通过父进程而衍生出来的,那么子进程的退出与资源的回收定然与父进程有很大的相关性。当一个子进程要正常的终止运行时,或者该进程结束时它的主函数 main() 会执行 exit(n); 或者 return n,这里的返回值 n 是一个信号,系统会把这个 SIGCHLD 信号传给其父进程,当然若是异常终止也往往是因为这个信号。

在将要结束时的子进程代码执行部分已经结束执行了,系统的资源也基本归还给系统了,但若是其进程的进程控制块(PCB)仍驻留在内存中,而它的 PCB 还在,代表这个进程还存在(因为 PCB 就是进程存在的唯一标志,里面有 PID 等消息),并没有消亡,这样的进程称之为僵尸进程(Zombie)。

如图中第四列标题是 S,S 表示的是进程的状态,而在下属的第三行的 Z 表示的是 Zombie 的意思。( ps 命令将在后续详解)

正常情况下,父进程会收到两个返回值:exit code(SIGCHLD 信号)与 reason for termination 。之后,父进程会使用 wait(&status) 系统调用以获取子进程的退出状态,然后内核就可以从内存中释放已结束的子进程的 PCB;而如若父进程没有这么做的话,子进程的 PCB 就会一直驻留在内存中,一直留在系统中成为僵尸进程(Zombie)。

虽然僵尸进程是已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,在进程列表中保留一个位置,记载该进程的退出状态等信息供其父进程收集,从而释放它。但是 Linux 系统中能使用的 PID 是有限的,如果系统中存在有大量的僵尸进程,系统将会因为没有可用的 PID 从而导致不能产生新的进程。

另外如果父进程结束(非正常的结束),未能及时收回子进程,子进程仍在运行,这样的子进程称之为孤儿进程。在 Linux 系统中,孤儿进程一般会被 init 进程所“收养”,成为 init 的子进程。由 init 来做善后处理,所以它并不至于像僵尸进程那样无人问津,不管不顾,大量存在会有危害。

进程 0 是系统引导时创建的一个特殊进程,也称之为内核初始化,其最后一个动作就是调用 fork() 创建出一个子进程运行 /sbin/init 可执行文件,而该进程就是 PID=1 的进程 1,而进程 0 就转为交换进程(也被称为空闲进程),进程 1 (init 进程)是第一个用户态的进程,再由它不断调用 fork() 来创建系统里其他的进程,所以它是所有进程的父进程或者祖先进程。同时它是一个守护程序,直到计算机关机才会停止。

通过以下的命令我们可以很明显的看到这样的结构

1
pstree

或者从此图我们可以更加形象的看清子父进程的关系

通过以上的显示结果我们可以看的很清楚,init 为所有进程的父进程或者说是祖先进程

我们还可以使用这样一个命令来看,其中 pid 就是该进程的一个唯一编号,ppid 就是该进程的父进程的 pid,command 表示的是该进程通过执行什么样的命令或者脚本而产生的

1
ps -fxo user,ppid,pid,pgid,command

可以在图中看见我们执行的 ps 就是由 zsh 通过 fork-exec 创建的子进程而执行的

使用这样的一个命令我们也能清楚的看见 init 如上文所说是由进程 0 这个初始化进程来创建出来的子进程,而其他的进程基本是由 init 创建的子进程,或者是由它的子进程创建出来的子进程。所以 init 是用户进程的第一个进程也是所有用户进程的父进程或者祖先进程。(ps 命令将在后续课程详解)

就像一个树状图,而 init 进程就是这棵树的根,其他进程由根不断的发散,开枝散叶

进程组与 Sessions

每一个进程都会是一个进程组的成员,而且这个进程组是唯一存在的,他们是依靠 PGID(process group ID)来区别的,而每当一个进程被创建的时候,它便会成为其父进程所在组中的一员。

一般情况,进程组的 PGID 等同于进程组的第一个成员的 PID,并且这样的进程称为该进程组的领导者,也就是领导进程,进程一般通过使用 getpgrp() 系统调用来寻找其所在组的 PGID,领导进程可以先终结,此时进程组依然存在,并持有相同的 PGID,直到进程组中最后一个进程终结。

与进程组类似,每当一个进程被创建的时候,它便会成为其父进程所在 Session 中的一员,每一个进程组都会在一个 Session 中,并且这个 Session 是唯一存在的,

Session 主要是针对一个 tty 建立,Session 中的每个进程都称为一个工作(job)。每个会话可以连接一个终端(control terminal)。当控制终端有输入输出时,都传递给该会话的前台进程组。Session 意义在于将多个 jobs 囊括在一个终端,并取其中的一个 job 作为前台,来直接接收该终端的输入输出以及终端信号。 其他 jobs 在后台运行。

前台(foreground)就是在终端中运行,能与你有交互的

后台(background)就是在终端中运行,但是你并不能与其任何的交互,也不会显示其执行的过程

工作管理

bash(Bourne-Again shell)支持工作控制(job control),而 sh(Bourne shell)并不支持。

并且每个终端或者说 bash 只能管理当前终端中的 job,不能管理其他终端中的 job。比如我当前存在两个 bash 分别为 bash1、bash2,bash1 只能管理其自己里面的 job 并不能管理 bash2 里面的 job

我们都知道当一个进程在前台运作时我们可以用 ctrl + c来终止它,但是若是在后台的话就不行了。

我们可以通过 & 这个符号,让我们的命令在后台中运行

1
ls &

图中所显示的 [1] 236分别是该 job 的 job number 与该进程的 PID,而最后一行的 Done 表示该命令已经在后台执行完毕。

我们还可以通过 ctrl + z 使我们的当前工作停止并丢到后台中去

被停止并放置在后台的工作我们可以使用这个命令来查看

1
jobs

其中第一列显示的为被放置后台 job 的编号,而第二列的  表示最近(刚刚、最后)被放置后台的 job,同时也表示预设的工作,也就是若是有什么针对后台 job 的操作,首先对预设的 job,- 表示倒数第二(也就是在预设之前的一个)被放置后台的工作,倒数第三个(再之前的)以后都不会有这样的符号修饰,第三列表示它们的状态,而最后一列表示该进程执行的命令

我们可以通过这样的一个命令将后台的工作拿到前台来

1
2
3
#后面不加参数提取预设工作,加参数提取指定工作的编号
#ubuntu 在 zsh 中需要 %,在 bash 中不需要 %
fg [%jobnumber]

之前我们通过 ctrl + z 使得工作停止放置在后台,若是我们想让其在后台运作我们就使用这样一个命令

1
2
#与fg类似,加参则指定,不加参则取预设
bg [%jobnumber]

既然有方法将被放置在后台的工作提至前台或者让它从停止变成继续运行在后台,当然也有方法删除一个工作,或者重启等等

1
2
3
4
5
# kill 的使用格式如下
kill -signal %jobnumber

# signal 从 1-64 个信号值可以选择,可以这样查看
kill -l

其中常用的有这些信号值

信号值 作用
-1 重新读取参数运行,类似与 restart
-2 如同 ctrl+c 的操作退出
-9 强制终止该任务
-15 正常的方式终止该任务

注意
若是在使用 kill + 信号值然后直接加 pid,你将会对 pid 对应的进程进行操作
若是在使用 kill + 信号值然后 %jobnumber,这时所操作的对象是 job,这个数字就是就当前 bash 中后台的运行的 job 的 ID。

wget

wget 支持 HTTP,HTTPS 和 FTP 协议,可以使用 HTTP 代理。所谓的自动下载是指,wget 可以在用户退出系统的之后在后台执行。这意味这你可以登录系统,启动一个 wget 下载任务,然后退出系统,wget 将在后台执行直到任务完成

wget 可以跟踪 HTML 页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构。这又常被称作”递归下载”。

wget 非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性.如果是由于网络的原因下载失败,wget 会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。

curl

cURL 技术支持库是:libcurl。这就意味着你可以基于 cURL 编写整个程序,允许你基于 libcurl 库中编写图形环境的下载程序,访问它所有的功能。

cURL 宽泛的网络协议支持可能是其最大的卖点。cURL 支持访问 HTTP 和 HTTPS 协议,能够处理 FTP 传输。它支持 LDAP 协议,甚至支持 Samba 分享。实际上,你还可以用 cURL 收发邮件。

cURL 也有一些简洁的安全特性。cURL 支持安装许多 SSL/TLS 库,也支持通过网络代理访问,包括 SOCKS。这意味着,你可以越过 Tor 来使用cURL。

cURL 同样支持让数据发送变得更容易的 gzip 压缩技术。

curl --help 查看帮助

curl 的简单方法
curl -X METHOD -H HEADER -i

HTTP 动词
curl 默认的 HTTP 动词是 GET,使用 -X 参数可以支持其他动词。
$ curl -X POST www.qq.com
$ curl -X DELETE www.qq.com

显示响应 header 信息
$ curl -i www.qq.com
-i 参数可以显示 http response 的头信息,连同网页代码一起。

增加头信息
$ curl --header "Content-Type:application/json" http://example.com

支持重定向 Follow redirects
-L 参数,curl 就会跳转到新的网址。
$ curl -L www.qq.com

若不加 -L 则不会自动重定向

1
2
3
4
5
6
7
8
curl www.qq.com
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

输出到文件, 可以使用 -o 参数:
$ curl -o [文件名] www.qq.com

curl 常用命令总结

1
2
3
4
5
6
curl命令  访问网站 url
-I/--head 显示响应头信息
-m/--max-time 访问超时的时间
-o/--output 记录访问信息到文件
-s/--silent 沉默模式访问,就是不输出信息
-w/--write-out 以固定特殊的格式输出,例如:%{http_code},输出状态码

利用 curl 命令返回值确定网站是否正常
curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null www.baidu.com
若返回 200 则表示成功.

进行 get 请求
curl www.ithome.com

进行 post 请求
设置 http 代理
curl --proxy 10.5.3.9:80 https://www.so.com

curl 案例

Shell 脚本 curl 发起 http 请求,保存到文件

1
2
3
zhang@ThinkPad:~$ RESULT=$(curl -s "http://baidu.com")
zhang@ThinkPad:~$ echo $RESULT
<html> <meta http-equiv="refresh" content="0;url=http://www.baidu.com/"> </html>

总结

cURL 与 wget:到底哪一个才更适合你

wget 简单直接。这意味着你能享受它超凡的下载速度。wget 是一个独立的程序,无需额外的资源库,更不会做其范畴之外的事情。如果你想做一些更复杂的使用,直觉告诉你,你应该选择 cRUL。

cURL 是一个多功能工具。当然,它可以下载网络内容,但同时它也能做更多别的事情。你可以把 cURL 想象成一个精简的命令行网页浏览器。它支持几乎你能想到的所有协议,可以交互访问几乎所有在线内容。唯一和浏览器不同的是,cURL 不会渲染接收到的相应信息。

遇到问题

curl: (6) Could not resolve host: www.baidu.com

都说是 dns 的问题。

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# vim /etc/resolv.conf

// 原先的 DNS
# Generated by NetworkManager
nameserver 8.8.8.8

// 修改后的 DNS
# Generated by NetworkManager
nameserver 114.114.114.114
nameserver 8.8.8.8

参考

http://www.ruanyifeng.com/blog/2019/09/curl-reference.html

更换源

中科大源、清华源或阿里源可任意选择一。

https://mirrors.ustc.edu.cn
https://mirrors.tuna.tsinghua.edu.cn
https://mirrors.aliyun.com/ubuntu

Ubuntu 的软件源配置文件在 /etc/apt/sources.list。请将系统自带的该文件做个备份。

方式一:使用 sed 命令进行替换

http://archive.ubuntu.com/ 替换为 http://mirrors.ustc.edu.cn 即可。可以使用如下命令:

1
sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list

方式二:直接覆盖

以 20.04 LTS 为例,copy 内容覆盖掉 /sources.list 即可。

然后旧版本请运行 sudo apt-get update,新版本请运行 sudo apt update 更新索引以生效。

启用 ssh

先通过 bash 进入子系统修改配置

1
2
3
4
Port = 22 # 默认是 22 端口,如果和 windows 端口冲突或你想换成其他的否则不用动
#ListenAddress 0.0.0.0 # 如果需要指定监听的 IP 则去除最左侧的井号,并配置对应 IP,默认即监听 PC 所有 IP
PermitRootLogin no # 如果你需要用 root 直接登录系统则此处改为 yes
PasswordAuthentication yes # 将 no 改为 yes 表示使用帐号密码方式登录

如果文件不存在说明尚未安装,则执行安装 apt get install openssh-server

之后使用 service ssh start 即可。

然后客户端 ssh 用户名@localhost 可进行登录即可。

ssh 相关知识

  • 查看 ssh 服务状态
    service ssh start
  • 查看 ssh 服务状态
    service ssh status
  • 查看 ssh 服务状态
    service ssh restart
  • 查看 ssh 服务状态
    service ssh stop
  • 生成对应的 rsa, ecdsa, ed25519 三种类型的秘钥

启用 lrzsz

1
sudo apt get install lrzsz

centos 中

sudo yum install lrzsz

常用命令

更新和升级包

1
sudo apt update && sudo apt upgrade

查看 Description 加上 -d
查看当前系统版本,查看版本信息加上 -c
查询全部信息,加上 -a

1
lsb_release -a

遇到过的问题

System has not been booted with systemd as init system

原因是你想用 systemd 命令来管理 Linux 上的服务,但你的系统并没有使用 systemd,(很可能)使用的是经典的 SysV init(sysvinit)系统。

答案很简单,就是不要使用 systemctl 命令,而是使用等同的 sysvinit 命令。相反,可以使用对应的 sysvinit 命令。

Systemd command Sysvinit command
systemctl start service_name service service_name start
systemctl stop service_name service service_name stop
systemctl restart service_name service service_name restart
systemctl status service_name service service_name status
systemctl enable service_name service service_name on
systemctl disable service_name service service_name off

Raspberry Pi

许多操作系统可用于 Operating system images – Raspberry Pi,包括 Raspberry Pi OS,我们的官方支持的操作系统,以及来自其他组织的操作系统。

Raspberry Pi Imager 是为 microSD 卡安装操作系统的一种快速简便的方法,可以与您的 Raspberry Pi 一起使用。或者,从下面的操作系统中选择,可以手动下载和安装。

Raspberry Pi Desktop for PC and Mac
使用 Raspberry Pi 的 Debian 桌面系统是我们的 PC 和 Mac 操作系统。它提供 Raspberry Pi 操作系统桌面,以及大多数推荐的 Raspberry Pi 操作系统软件,适用于任何 PC 或苹果 Mac 电脑。
如果你的旧电脑已经不能运行现代的商业操作系统了,那么可以尝试一下使用 Raspberry Pi 桌面的 Debian: 它可以让你的电脑再次使用。

如何烧录树莓派 OS / 优麒麟(树莓派版)到您的 microSD 存储卡

  1. 树莓派官网 下载 raspberry pi image 工具
  2. 选择镜像
  3. 选择 sd 卡
  4. 点击 write

与树莓派搭配使用的工具: SDFormatter 介绍
https://www.sdcard.org/downloads/formatter/index.html

SDFormatter 是一个简单和有用的 SD 卡修复工具也是内存卡修复工具,专门设计为 TF 卡/手机 SD 卡/ SD 卡 / SDHC 卡 / SDXC 内存卡修复使用,此内存卡修复工具除了可以在 WIN 系统上运行,还支持苹果 MACOSX 系统上运行。

注:本工具只能格式化修复你的内存卡,不能恢复你的内存卡数据,但可以让你的内存卡起死回生,所以你也可以先进行数据恢复再使用本工具修复!

参考

dpkg 命令的详细使用教程_阿力 php 的博客-CSDN 博客_dpkg 命令
dpkg 命令的用法_小绵羊的学习之路的博客-CSDN 博客_dpkg 命令

顺序执行

简单的顺序执行你可以使用;来完成,比如上述操作你可以:

1
2
$ sudo apt-get update;sudo apt-get install some-tool;some-tool
# 让它自己运行

选择执行
可以从$?环境变量获取上一次命令的返回结果
成功则返回 0( 看做 false) , 失败为 1 (看做 true)

&&就是用来实现选择性执行的,它表示如果前面的命令执行结果返回 0 (false)则执行后面的,否则不执行

|| 就是用来实现选择性执行的,它表示如果前面的命令执行结果返回 非0 (true)则执行后面的,否则不执行

如果有则做 -> 为0(false) 再做 ||

1
which cowsay>/dev/null && cowsay -f head-in ohch~

如果没有才做 -> 为1(true)再做 &&

1
which cowsay>/dev/null || echo "cowsay has not been install, please run 'sudo apt-get install cowsay' to install"

管道

管道是什么?管道是一种通信机制,通常用于进程间的通信(也可通过 socket 进行网络通信),它表现出来的形式就是将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin)。

管道又分为匿名管道和具名管道(这里将不会讨论在源程序中使用系统调用创建并使用管道的情况,它与命令行的管道在内核中实际都是采用相同的机制)。我们在使用一些过滤程序时经常会用到的就是匿名管道,在命令行中由|分隔符表示,|在前面的内容中我们已经多次使用到了。具名管道简单的说就是有名字的管道,通常只会在源程序中用到具名管道。下面我们就将通过一些常用的可以使用管道的"过滤程序"来帮助你熟练管道的使用。

有太多内容,屏幕不能完全显示,这时候可以使用滚动条或快捷键滚动窗口来查看。不过这时候可以使用管道:

1
ls -al /etc | less

通过管道将前一个命令(ls)的输出作为下一个命令(less)的输入,然后就可以一行一行地看。

cut 命令

cut 命令,打印每一行的某一字段

打印 /etc/passwd 文件中以:为分隔符的第 1 个字段和第 6 个字段分别表示用户名和其家目录:

1
cut /etc/passwd -d ':' -f 1,6
1
2
3
4
5
6
7
8
# 前五个(包含第五个)
$ cut /etc/passwd -c -5
# 前五个之后的(包含第五个)
$ cut /etc/passwd -c 5-
# 第五个
$ cut /etc/passwd -c 5
# 2到5之间的(包含第五个)
$ cut /etc/passwd -c 2-5

grep 命令

grep 命令是很强大的,也是相当常用的一个命令,它结合正则表达式可以实现很复杂却很高效的匹配和查找,不过在学习正则表达式之前,这里介绍它简单的使用,而关于正则表达式后面将会有单独一小节介绍到时会再继续学习 grep 命令和其他一些命令。

一般形式

1
grep [命令选项]... 用于匹配的表达式 [文件]...

还是先体验一下,我们搜索 /home/shiyanlou 目录下所有包含 “shiyanlou” 的文本文件,并显示出现在文本中的行号:

1
grep -rnI "shiyanlou" ~

-r 参数表示递归搜索子目录中的文件,-n 表示打印匹配项行号,-I 表示忽略二进制文件。这个操作实际没有多大意义,但可以感受到 grep 命令的强大与实用。

当然也可以在匹配字段中使用正则表达式,下面简单的演示:

1
2
# 查看环境变量中以"yanlou"结尾的字符串
export | grep ".*yanlou$"

其中$就表示一行的末尾。

wc 命令

wc 命令用于统计并输出一个文件中行、单词和字节的数目,比如输出/etc/passwd文件的统计信息:

1
wc /etc/passwd

分别只输出行数、单词数、字节数、字符数和输入文本中最长一行的字节数:

1
2
3
4
5
6
7
8
9
10
# 行数
$ wc -l /etc/passwd
# 单词数
$ wc -w /etc/passwd
# 字节数
$ wc -c /etc/passwd
# 字符数
$ wc -m /etc/passwd
# 最长行字节数
$ wc -L /etc/passwd

再来结合管道来操作一下,下面统计 /etc 下面所有目录数:

1
$ ls -dl /etc/*/ | wc -l

sort 命令

这个命令前面我们也是用过多次,功能很简单就是将输入按照一定方式排序,然后再输出,它支持的排序有按字典排序,数字排序,按月份排序,随机排序,反转排序,指定特定字段进行排序等等。

默认为字典排序:

1
cat /etc/passwd | sort

反转排序:

1
cat /etc/passwd | sort -r

按特定字段排序:

1
cat /etc/passwd | sort -t':' -k 3

上面的 -t 参数用于指定字段的分隔符,这里是以 “:” 作为分隔符;-k 字段号 用于指定对哪一个字段进行排序。这里 /etc/passwd 文件的第三个字段为数字,默认情况下是以字典序排序的,如果要按照数字排序就要加上 -n 参数:

1
cat /etc/passwd | sort -t':' -k 3 -n

uniq 去重命令

uniq 命令可以用于过滤或者输出重复行。

  • 过滤重复行

我们可以使用 history 命令查看最近执行过的命令(实际为读取${SHELL}_history 文件,如我们环境中的~/.zsh_history 文件),不过你可能只想查看使用了哪个命令而不需要知道具体干了什么,那么你可能就会要想去掉命令后面的参数然后去掉重复的命令:

1
history | cut -c 8- | cut -d ' ' -f 1 | uniq

然后经过层层过滤,你会发现确是只输出了执行的命令那一列,不过去重效果好像不明显,仔细看你会发现它确实去重了,只是不那么明显,之所以不明显是因为 uniq 命令只能去连续重复的行,不是全文去重,所以要达到预期效果,我们先排序:

1
2
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq
# 或者$ history | cut -c 8- | cut -d ' ' -f 1 | sort -u

这就是 Linux/UNIX 哲学吸引人的地方,大繁至简,一个命令只干一件事却能干到最好。

  • 输出重复行
1
2
3
4
# 输出重复过的行(重复的只输出一个)及重复次数
$ history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -dc
# 输出所有重复的行
$ history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -D

systemctl

systemctl 命令有两大类功能:

  • 控制 systemd 系统
  • 管理系统上运行的服务

linux systemctl 命令详解_Linux_脚本之家
https://www.jb51.net/article/136559.htm

find

1
2
# 移除 15 天前不包含当天的安装包
find -maxdepth 1 -mtime +15 -name 'thingsx*.rpm' -exec rm {} \;

关于时间的信息有三个:最近访问时间 access time (-atime)、最近更改时间 modify time (-mtime) 和 最近状态改动时间 change time(-ctime)

使用 find 命令在当前目录不包含子目录中查找文件
-maxdepth 1

-mtime n : n 为数字,意思为在 n 天之前的“一天之内”被更改过内容的文件
-mtime +n : 列出在 n 天之前(不含 n 天本身)被更改过内容的文件名
-mtime -n : 列出在 n 天之内(含 n 天本身)被更改过内容的文件名

授权相关

chmod 命令

chmod 命令是非常重要的,用于改变文件或目录的访问权限。用户用它控制文件或目录的访问权限。

[u]ser 代表用户.
[g]roup 代表用户组.
[o]thers 代表其他.
a 代表所有

这意味着 chmod u+x somefile 只授予这个文件的所属者执行的权限
= chmod +x somefile 和 chmod a+x somefile 是一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Linux 系统中的每个文件和目录都有访问许可权限,
用它来确定谁可以通过何种方式对文件和目录进行访问和操作。
文件或目录的访问权 限分为只读,只写和可执行三种。

这里显示的权限是依次排列的,分别为:[用户][同组][其他]
用户权限,就是你自己的权限。英文:user,简写:u(覆盖标号123)
用户组权限,就是和你同组的人的权限。英文:group,简写:g(覆盖标号456)
其他权限,就是不和你同组的人的权限。英文:others,简写:o(覆盖标号789)
所有人的权限,英文:all,简写:a

r, 即 Read,读,权限值为4
w,即 Write,写,权限值为2
x,即 eXecute,执行,权限值为1
-,在标号 0 位置,表示普通的文件
-,其他位置,表示对应权限未开启,不具备权限
d,即 directory,表示目录文件

无任何权限:数字 0 表示
开所有权限:数字 7 表示,即 7=4+2+1

chmod 命令是用于改变文件或目录的访问权限。

+ 表示增加权限,如 u+x, u+r, u+w, g+w, g+r, o+r, a+r 等
- 表示取消权限,如 u-x, u-r, u-w, g-w, g-r, o-r, a-r 等
= 表示赋予给定权限,并取消其他所有权限(如果有的话,如原来u是rwx,设置u=r,u就剩r)

chgrp命令

功能:改变文件或目录所属的组。

语法:chgrp [选项] group filename¼

chown 命令

功能:更改某个文件或目录的属主和属组。这个命令也很常用。例如 root 用户把自己的一个文件拷贝给用户 yusi,为了让用户 yusi 能够存取这个文件,root 用户应该把这个文件的属主设为 yusi,否则,用户 yusi 无法存取这个文件。

语法:chown [选项] 用户或组 文件

说明:chown将指定文件的拥有者改为指定的用户或组。用户可以是用户名或用户ID。组可以是组名或组 ID。文件是以空格分开的要改变权限的文件列表,支持通配符。

其他命令

zcat

zcat 命令用于不真正解压缩文件,就能显示压缩包中文件的内容的场合。用于查看压缩文件的内容,而无需对其进行解压缩。 它将压缩文件扩展为标准输出,使您可以查看其内容。 另外,zcat 与运行 gunzip -c 命令完全相同。

SELinux

它叫做“安全增强型 Linux(Security-Enhanced Linux)”,简称 SELinux,它是 Linux 的一个安全子系统。

  1. 运行 getenforce 命令查看 SELinux 的当前状态。

查看SELinux状态

  • 如果 SELinux 状态参数是 Disabled, 则 SELinux 为关闭状态。
  • 如果 SELinux 状态参数是 Enforcing,则 SELinux 为开启状态。本示例中 SELinux 为开启状态,因此需要关闭 SELinux。

2. 关闭 SELinux。如果 SELinux 为关闭状态可以忽略此步骤。

  • 如果您想临时关闭 SELinux,运行命令 setenforce 0。

说明 这只是暂时关闭 SELinux,下次重启 Linux 后,SELinux 还会开启。

  • 如果您想永久关闭 SELinux,运行命令 vi /etc/selinux/config 编辑 SELinux 配置文件。回车后,把光标移动到 SELINUX=enforcing 这一行,按 i 键进入编辑模式,修改为 SELINUX=disabled, 按 Esc 键,然后输入 :wq 并按Enter 键以保存并关闭 SELinux 配置文件。

说明 如果您想重新开启 SELinux,请参见SELinux 的官方文档

工具软件

rsync

rsync
https://rsync.samba.org/

Rsync 是一个提供快速增量文件传输的开源实用程序。Rsync 在 GNU 通用公共许可协议下可以免费使用,目前由韦恩•戴维森(waynedavison)维护。

参考

0%