[TOC]

文件管理与常用命令

文件的目录配置

/:根目录,文件系统的顶层。 与开机有关
/home:用户主目录。
/bin:必备的二进制可执行文件。 最基本的命令 比如:cat mv mkdir
/sbin:系统管理二进制文件。
/etc:配置文件。 只有 root 可以更改,一般着只能查阅
/var:可变数据(日志、假脱机文件)。 与系统运行有关
/usr:用户程序和数据。 与系统操作有关
/lib:共享库。 函数库
/tmp:临时文件。
/opt: 第三方软件 存储第三方
/sbin : 开机过程所需要的指令

起点是根目录,文件可以是本地也可以是网络文件,每个文件在此目录树中的文件是独一无二的

文件系统与目录树的关系

硬盘需要分区,格式化,挂载才能使用。

每个文件都会有一个 inode
对于目录,inode 存储属性,权限,data block号。data block号存储的是文件名与文件对应的inode
对于普通文件,inode 存储属性,权限,以及分配的一组data block号(这里存储的是文件内容)

目录树的读取方式

从根目录的inode 逐层往下访问

文件和目录的布局

绝对路径和相对路径

绝对路径:从根开始
相对路径:相对与当前路径的相对位置
假设现在在home 目录中,需要进入 var/log

cd /home/var/log    绝对路径
cd ../var/log 相对路径

. 代表当前目录
.. 代表返回上一层目录
- 回到上一个工作目录
~ 家目录 home
向下一层:直接写文件名字就行。或者 ./ 文件名 (也是相对路径)

文件-权限 (Linux5.2)

用户与用户组

  • 文件拥有者(user)
  • 组用户(group) 被给权限的成员
  • 其他(others)
    万能用户:root

文件属性详解

-rwx-w-rw- 实际上除了9个“r w x”最前面是代表文件是“目录,文件,链接文件”
‘r’ 对于文件,具有文件读取(data block)“数据块内容”内容。对于目录,具有浏览目录(data block)的权限。
‘w ‘’ 对于文件,具有新增,修改文件内容(data block)的权限。 对于目录,具有删除、移动 目录内文件(data block)的权限
‘x’ 对于文件,具有执行文件的权限。 对目录,具有进入目录权限。

文件类型权限、链接数、

修改文件权限

命令 chomd 选项 文件

数字表示法

r w x 分别用数字 4 2 1 (二进制)表示,再把所授予的权限相加而成。
-rwxrw-r– 764 (每个数字八进制 111 110 100) 给其他人写内容的权限更改为766

文字表示法

u user
g group
o others
a all 以上三种用户
符号: + 添加某种权限,- 减去某种权限,= 赋予并取消原来权限
chmod u +x g=rw o+w abc

修改文件所有者

命令 chown 选项 用户和属组 文件列表

chown [选项] 新所有者:新组 文件

# 更改文件所有者
sudo chown 新所有者 文件

#更改文件的所有者和组
sudo chown 新所有者:新组 文件

#. 更改目录及其子目录中文件的所有者(递归)
sudo chown -R 新所有者:新组 目录

#只更改文件的组
sudo chgrp 新组 文件
sudo chown :新组 文件





文件默认权限

umask 命令用于指定用户在建立文件和目录时的权限默认值,umask值称之为权限掩码。

文件预设权限 -rw-rw-rw- 666 目录的预设文件 -rwxrwxrwx 777
普通用户的umask为002 (原来有的减去,没有的忽略掉) 对于文件:664 rw-rw-r– 对于目录:775 rwxrwxr-x
root用户的umask为022

特殊权限

SUID

只对二进制有效,是设置在可执行文件上的权限位。它允许用户以文件所有者的身份执行文件,而不是以当前用户的身份执行。

一个例子:rwxr-xr-x 变成了 rwsr-xr-x
1.tester用户对于/usr/bin/passwd -rwsr-xr-x 这个程序具有执行权限,因此可以执行passwd程序
2.passwd程序的所有者为root
3.tester用户执行passwd程序的过程中会暂时获得root权限
4.因此tester用户在执行passwd程序的过程中可以修改/etc/shadow 文件

可能会有一个问题,既然不在用户中或者组用户中,为什么不赋予w权限,而是要用 SUID?

  • 因为有些文件只能root修改
如何设置与删除SUID
创建
chmod u+s file_name
chmod 4766 file.name 4 代表SUID 中的s
删除
chmod u-s test.txt
chmod 0766 test2.txt
小写s 与大写S 的区别

如果一开始文件就没有 执行,再设置suid 位 小写的s将会变成大写 的S
也就是出现了错误。

如何查找所有了设置SUID 的文件

SGID

只对二进制有效,任何一个用户在原本文件也是要有执行权力的。SGID 可以应用于文件和目录,但它在这两者上的行为不同。

  • 作用到目录:
    当目录设置了 SGID 位时,所有在该目录下创建的文件和子目录将继承该目录的组(而不是创建文件者的默认组)。

  • 作用到文件:当文件具有 SGID 位时,执行该文件的用户将暂时以该文件的组权限执行,而不是以用户所在组的权限执行。

#设置sgid
chmod g+s filename_or_directory

SBIT

sticky bit
只针对目录有效。只有文件的所有者或root 用户才能删除该目录下的文件或子目录,即使其他用户对该目录具有写权限。
说白了,就是针对目录,用于阻止非文件的所有者进行删除

#设置SBIT
chmod +t directory

suid sgid sbit 设定

数字:4为SUID,2为SGID,1为SBIT
suid u+s,sgid g+s,SBIT o+t

suid rwsr-xr-x
sgid rwxr-sr-x
sbit rwxr-xr-t

练习

当一个文件的权限为–rwxrwxrwx则表示这个文件的意义为?任何人都可以读、修改或编辑、执行,但未必能删除。
文件是否能删除: 取决于该文件所在的目录下的权限 对于属于这个文件的 user 或着group或者其他人, 看此文件的权限和该文件所在目录当中的权限

文件及文件管理

文件类型

在linux 系统中,一切都是文件。对所有文件(目录、字符设备、块设备、套接字、打印机、进程、线程、管道等)操作

- 表示普通文件。文本,二进制,脚本文件

d 表示目录。

l 表示符号链接。符号链接类似于 Windows 系统中的快捷方式。

b 表示块设备文件。设备文件是与硬盘、光驱等设备交互的接口。它们以块为单位读写数据。

c 表示字符设备文件。字符设备文件是与终端、键盘、鼠标等设备交互的接口。它们以字符为单位进行数据传输。

p 表示管道文件。在进程之间传递数据,允许一个进程将输出作为另一个进程的输入。

s 表示套接字文件。套接字文件用于网络通信或进程间通信,它是一种特殊的文件类型,用于实现数据流的通信。

文件扩展名

inux系统中文件的扩展名是没有意义的。一个文件能否执行取决于是否拥有“x”权限。扩展名仅仅用来了解文件是什么 。 例如,一个文件叫 abc.exe

文件名的规则

文件名 分大小写
文件名的字符包括: 字母,数字,点,下划线,连字符-

目录操作命令

-help 非常有用

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

  • cd 更改当前目录,cd 目录名

  • mkdir [选项] 文件名

    选项 意义
    -m 对新建目录设置存取权限
    -p 在创建目录时,如果父目录不存在,则同时创建该目录及该目录的父目录
$ # 创建一个目录,名为 DIR_NAME
$ mkdir [OPTION] DIR_NAME...
$ # 创建两个目录
$ mkdir test1 test2
¥ # 创建路径
$ mkdir -p test1/test2/test3/
  • rmkdir 删除目录(必须为空) rmdir [选项名] 目录名 -p 在删除目录的时候,一同删除父目录(父目录中必须没有其他目录以及文件)

  • ls 显示文件和目录列表 ls [选项名] [文件名或目录名]
    -a 所有文件,包括以“.”开始的隐藏文件 。 -l 列出文件的详尽信息(权限,所有者,文件大小,修改时间名称) -t 根据最后修改时间的顺序来列出文件。 -r 显示出目录下所有子目录的文件名。

文件操作命令

cat

cat file.txt 输出全部内容,cat filetxt file2.txt 查看 file1.txt 与 file2.txt 连接后的内容
cat file1 file2 > file3 将问两盘文章合并到文章3 中
cat 这里是 concatenate(连接)的缩写,因为 cat 工具实际的功能是连接多个文件,然后输出。但是当只有一个文件的时候,cat 就会直接输出这个文件,所以 cat 最常见的用途就是输出单个文件。
cat [选项] [文件名] -n 给所有行数加上数字 -b 空白行不进行编写号码 -s 将连续两行以上的空白行替换乘一行空白行。

可以创建或者编辑文件

# 显示文件内容
cat filename
# 创建并且输出内容
cat > notes.txt
This is a new file.
Ctrl + D

nano filename
ctrl + x
# 追加内容到已有文件中
cat file1.txt >> existingfile.txt


  • head 显示文章的头部部分,默认情况下只显示文章的前10行内容。 head [选项] 文件名
    -n num 显示指定文件的前num 行。 -c num 显示文件的前num 个字符 。 - num 从倒数第几行开始显示指定文件的内容。

  • tail 用于显示文件的末尾部分,默认显示文件的末尾10行内容。tail [选项] 文件名
    -n num: 显示指定文件的末尾num行-c num: 显示指定文件的末尾num个字符 +num: 从第num行开始显示指定文件的内容

  • more 分屏显示文件内容。

less

less 和 cat 的区别在于,cat 会一次性打印全部内容到终端中并退出,而 less 一次只显示一页,且支持向前/后滚动、搜索等功能。如果要在一个大文件中(例如 man page)查找一部分内容,less 通常要比 cat 方便得多。
一些快捷键:

按键 效果
d/u 向下/上滚动半页
Page Down / Page Up f / b 向下/上滚动一整页(forward/back)
g / G 跳转到文件开头/结尾
j / Down 向下移动一行
k / Up 向上移动一行
/PATTERN 在文件中搜索 PATTERN
n / N 跳转到下一个/上一个找到的 PATTERN

touch 创建文件/修改文件时间标签

为甚叫touch 不叫 creat?
touch 工具实际上的功能是修改文件的访问时间(access time, atime)和修改时间(modification time, mtime),可以当作是摸(touch)了一下文件,使得它的访问与修改时间发生了变化。当文件不存在时,touch 会创建新文件,所以创建文件也就成为了 touch 最常见的用途。

创建一个新文件,更改现有的文件标签.

按键 效果
-d yyyymmdd 把文件存取和修改时间 改为年月日
-a 只把文件的存取,访问时间改为当前时间
-m 只把文件的修改时间 改为当前时间
-c 即使没有该文件也不会创建新文件
  • sort 文件内容排序 对文本文件的各行进行排序

cp 复制文件和目录

$ # 将 SOURCE 文件拷贝到 DEST 文件,拷贝得到的文件即为 DEST
$ cp [OPTION] SOURCE DEST

$ # 将 SOURCE 文件拷贝到 DIRECTORY 目录下,SOURCE 可以为不止一个文件
$ cp [OPTION] SOURCE... DIRECTORY
$ cp source_file destination_directory/
cp file1.txt /home/user/Documents/


$ # 将 dir1 文件夹及其所有子文件复制到同目录下的 test 文件夹中
$ cp -r dir1 ./test/
选项 含义
-r,-R,–recursive 递归复制,常常用于复
制目录
-f,–force 覆盖目标地址同名文件
-u,–update 只有当源文件比目标文件新的时候才进行复制
-l,–link 创建硬链接
-s,–symbolic_link 创建软连接

mv 移动文件和目录

和cp 的用法相似。类似于windows 下的剪切。

$ # 将 SOURCE 文件移动到 DEST 文件
$ mv [OPTION] SOURCE DEST
$ # 将 SOURCE 文件移动到 DIRECTORY 目录下,SOURCE 可以为多个文件
$ mv [OPTION] SOURCE... DIRECTORY

常用的选项:

选项 含义
-f /–force 覆盖目标地址同名文件
-u/–update 只有源文件闭目标文件更新的时候才会移动

为什么mv 命令不需要-r 参数,但是cp 需要-r 参数?
复制文件夹的过程需要创建新的文件和文件夹,而移动文件夹的操作可以看作是「重命名」。
mv 事实上调用了 rename 系统调用,即重命名。由于目录是一个树状结构,那么移动文件夹只需要修改这个「文件夹节点」本身的位置与名称即可,不需要对文件夹内的文件(它的子树)做递归的操作。

rm 删除文件和目录

$ # 删除 FILE 文件,FILE 可以为多个文件。
$ # 如果需要删除目录,需要通过 -r 选项递归删除目录
$ rm [OPTION] FILE...
$ # 删除 test1/、test2/、file1.txt 这些文件、目录。其中,这些文件或者目录可能不存 在、写保护或者没有权限读写:
$ rm -rf test1/ test2/ file1.txt

常用选项:

选项 含义
-f/–force 无视不存在或者没有权限的文件和参数
-r/-R/–recursive 递归删除目录及其子文件
-d,–dir 删除空目录

sort

用于文本的行 排序。默认升序,按照每行的字典序进行排序
一些基本用法:
sort[选项]文件列表

选项 含义
-r 降序 (从大到小)排序
-u 去除重复行
-o [file] 指定输出文件,将排序的结果存入指定文件
-t “分割字符” 指定排序时所用的栏位分隔符
-n 用于数值排序,否则“15”会排在“2”前
-k 第多少列 -k1.2 按照第一列的第二个字符

diff

用于比较两个文件内容的不同 ,主要是纯文本文件

wc

统计指定文件的字节数,字数,行数

选项 含义
-c 统计字节数
-l 统计行数
-m 统计字符数
-w 统计字数

文件搜索

文件通配符

星号 * : 匹配任意长度的文件名字符串
问号 ? : 匹配任一单字符
点字符(.):当它作为文件名或路径名分量的第一个字符时 ,必须显式匹配

  • file匹 配 file , makefile , 不 匹 配 . profile文 件
    try*c 匹配try1.c try.c try.basic

文件查找命令

查找指定文件find命令

命令功能: 查找满足条件的文件 ,功能强大。
命令格式: find [搜索的路径] [选项] [-print -exec -ok]

find命令的匹配表达式主要有以下几种类型: -

  • -name filename: 查 找 指 定 名 称 的 文 件 。

  • -user username:查找属于指定用户的文件。

  • -group grpname:查找属于指定组的文件。

常用的表达式:

-name *.ext 文件名后缀为 ext。其中 * 是任意匹配符
-type d 文件类型为目录,其他的类型例如 f(普通文件)
-size +1M 大于 1M 的文件,+ 代表大于这个大小,对应地,- 代表小于之后的大小
-or 或运算符,代表它前后两个条件满足一个即可
  • -size n:查找比n 大或小的文件 符号nc 表示查找大小为n 个byte的文件 ,nk表示n * 1024bytes

  • -inum n:查找索引节点号为n 的文件。

  • -type:查找指定类型的文件。文件类型块设备文件) 、c (字符 设备文件) 、d(目录) 、p(管道文件) 、l(符号链接文件) 、f(普通文 件)。

  • -atime n:查找n天前被访问过的文件 “ +n ”表示超过n天前被访问的文件;“ -n ”表示n天内被访问 的文件 ,n 表示n天之前的[ 一天之内]被访问过的文件。

  • -mtime n:类似于atime,但检查的是文件内容被修改的时间。

  • -ctime n:类似于atime,但检查的是文件索引节点被改变的时间。

  • -perm mode:查找与给定权限匹配的文件 ,必须以八进制的形式给出访问权限。mode表示权限 为mode,-mode搜索权限包括mode的文件(范围比mode大) ,/mode表示搜索符合任何一 个 权限的文件(范围比mode小)。

  • -newer file:查找比指定文件新的文件 ,即最后修改时间离现在较近。

对文件的操作命令

对文件的操作命令
-exec command {} ; 对匹配指定条件的文件执行command命令。 \是转义
-ok command {} ; 与上面相同,执行command 命令的时候会请求用用户确定
-print 显示查找结果

{}代表所查到的符合条件的路径名。注意 ,两花括号间无空格 ,之后的空格不可省略

locate 命令(速度快)

命令格式 : locate [选项] [文件名]

where is 命令

命令功能: 用来寻找命令的可执行文件所在的位置。
命令格式:where is [选项] [文件名]
常用参数选项:
-b: 只查找二进制文件。
-m: 只查找命令的联机帮助手册部分。
-s: 只查找源代码文件。

g rep 命令

命令功能: 用于查找文件中包含有指定字符串的行
命令格式:
g rep [选项] 查找模式 [文件名1 ,文件名2 , …]
g rep [选项] [-e 查找模式| -f 文件] [文件名1 ,文件名2 , …]

硬链接和符号链接

文件的压缩

文件归档

tar
$ # 命令格式如下,请参考下面的使用样例了解使用方法
$ tar [OPTIONS] FILE...
选项 含义
-A 将一个存档文件中的内容追加到另一个存档文件中
-r, –append 将一些文件追加到一个存档文件中
-c, –create 从一些文件创建存档文件
-t, –list 列出一个存档文件中的内容
-x, –extract, –get 从存档文件中提取出文件,还原文件
-f, –file=ARCHIVE 使用指定的存档文件
-C, –directory=DIR 指定输出的目录
添加压缩选项可以使用压缩算法进行创建压缩文件或者解压压缩文件:
选项 含义
-z, –gzip, –gunzip, –ungzip 使用 gzip 算法处理存档文件
-j, –bzip2 使用 bzip2 算法处理存档文件
-J, –xz 使用 xz 算法处理存档文件
#将 file1、file2、file3 打包为 target.tar:
$ tar -c -f target.tar file1 file2 file3

#将 target.tar 中的文件提取到 test 目录中:
$ tar -x -f target.tar -C test/

#将 file1、file2、file3 打包,并使用 gzip 算法压缩,得到压缩文件 target.tar.gz
$ tar -cz -f target.tar.gz file1 file2 file3

# 将压缩文件 target.tar.gz 解压到 test 目录中
$ tar -xz -f target.tar.gz -C test/

#将 archive1.tar、archive2.tar、archive3.tar 三个存档文件中的文件追加到#archive.tar 中
$ tar -Af archive.tar archive1.tar archive2.tar archive3.tar

# 列出 target.tar 存档文件中的内容
$ tar -t -f target.tar

$ # 打印出文件的详细信息
$ tar -tv -f target.tar

tar 名字来源于英文 tape archive,原先被用来向只能顺序写入的磁带写入数据。tar 格式本身所做的事情非常简单:把所有文件(包括它们的“元数据”,包含了文件权限、时间戳等信息)放在一起,打包成一个文件。注意,这中间没有压缩的过程。
为了得到更小的打包文件,方便存储和网络传输,就需要使用一些压缩算法,缩小 tar 文件的大小。这就是 tar 处理它自己的打包文件的逻辑。在 Windows 下的一部分压缩软件中,为了获取压缩后的 tar 打包文件的内容,用户需要手动先把被压缩的 tar 包解压出来,然后再提取 tar 包中的文件。

vim 以及c 开发工具

nano 相关

nano [options] filename

命令

nano 打开,然后进入编辑,保存更改Ctrl + O 然后Enter
退出 nano,Ctrl+X。
-B 保存更改之前备份当前文件。 nano -B myfile.txt
-I 启用自动缩进。 nano -I myfile.txt
-N 无需从 DOS/Mac 格式转换。 nano -N myfile.txt
-T 将制表符的大小设置为给定的空格数。 nano -T 4 myfile.txt
-U 启用撤消功能。 nano -U myfile.txt
-Y 语法突出显示。 nano -Y sh myfile.sh
-c 不断显示光标位置。 nano -c myfile.txt
-i 自动缩进新行。 nano -i myfile.txt
-k 切换剪切以便从光标位置剪切。 nano -k myfile.txt
-m 启用鼠标支持。 nano -m myfile.txt

vim

有三种工作方式:命令模式,插入模式,底行模式。

  • 命令模式
    键入“vi 文件名”就可启动vi。“命令模式”是进入vi编辑器的初始模式
    |命令模式下的常用操作| 含义|

    重点命令 含义
    n n表示数字,按下数字n后再按空格,光标会向右移动n个字符。
    n N为数字,光标乡下移动n行
    0或Home键 移动到这一行的最前面字符处
    $或End键 移动到这一行的最后面的字符处
    G 移动到该文件的最后一行
    nG n为数字,移动到该文件的第n行。例如20G
    x,X 在当前行中,x为向后删除一个字符(相当于[del ]按键),X为向前删除一个字(BackSpace)
    dd 删除游标所在的那一行
    ndd 删除光标所在的下n行
    yy 复制光标所在的一行
    nyy 复制光标所在的下n行
    p,P p为将已复制的数据在光标下一行贴上,P 则为贴在游标上一行!
    u 复原前一个动作。
  • 插入模式
    “插入模式”是vi编辑器最简单的模式,在该模式下没有繁琐的命令,用户从键盘输入得任何有效字符都被认为是正在编辑的文件内容,并显示在vi编辑器中。
    只有在插入模式下,才可以进行文本的输入操作.

    命令 功能
    i,I 进入插入模式(Insert mode): i为从目前光标所在处插入,Ⅰ为在目前所在行的第一个非空格符处开始插入。
    a,A 进入插入模式(Insert mode):a为从目前光标所在的下一个字符处开始插入,A为从光标所在行的最后一个字符处开始插入。
    o,O 进入插入模式(Insert mode):这是英文字母o的大小写。o为「目前光标所在的下一行处插入新的一行』;0为在目前光标所在处的上一行插入新的一行!
    r,R 进入取代模式(Replace mode): r只会取代光标所在的那一个字符一次;R会一直取代光标所在的文字,直到按下ESC为止;
  • 底行模式
    “底行模式”是指可以在编辑器最底部的一行输入控制操作命令,主要用来进行一些文字编辑的辅助功能,比如字符串搜索、替代、保存文件,退出vi等。
    在“命令模式”下,通过输入冒号(:)、问号(?)或斜杠(/),可以切换至“底行模式”

    命令 功能
    :w 将编辑的数据写入硬盘文件中
    :w! 若文件属性为『只读』时,强制写入该文件。不过,到底能不能写入,还是跟你对该文件的权限有关.
    :q 离开vi
    :q! 曾经修改但是不想储存,!强制离开
    :wq 储存后离开 :wq! 为不进行储存强制离开
    :zz 如果文件没有更改,不进行储存离开;更改之后才会储存后离开
    /word 向光标之下寻找一个名称为word 的字符串
    ?word 像光标之上寻找字符串

暂存文件

在编辑文件的时候,会将文件暂存在该目录下生成 .filename.swap若vi编辑器非正常退出、掉线,则可用该文件进行救援。

拓展功能

  • 区块选择
    v : 字符选择,会将光标经过的地方反白选择。
    V :行选择,会将光标经过的地方行反白。
    Ctr+ v : 区块权责,可任意用长方形的方式选择文件。
  • 多文本编辑
    命令 功能

gcc

gcc 编译器对文件有预处理,编译,汇编,链接。
(源文件.c)预处理: 展开头文件,去掉注释行,宏替换。
编译 : 将源文件 编译 得到一个汇编文件
汇编:对文件进行汇编,得到一个二进制文件
链接: 对程序所需要的库进行链接,得到可执行的二进制文件

#进行预处理
gcc -E test.c -o test.i
#编译预处理之后的文件
gcc -S test.i -o test.s
#对汇编文件进行汇编
gcc -c test.s -o test.o
#将二进制文件与标准库进行连接,得到可执行的二进制文件
gcc test.o -o test

指定文件名 -o 参数,源文件可以写在-o 之前或者之后

四个阶段 作用
预处理阶段 处理头文件的引用,所以需要指明头文件的路径
编译阶段 不需要头文件,库
汇编阶段 与头文件和库的路径无关
连接阶段 将目标与所需要的库进行连接,指定路径

相关参数:

  • I 指定头文件的路径 大写的i
  • l 指定要使用的库 小写的l
  • L 指定库的路径 !
  • fPIC 生曾于位置无关的代码
  • shared 生成共享目标文件

静态库与动态库

静态库

静态库是一种打包文件的形式,将一组编译好的目标文件(.o 文件)合并到一个归档文件(.a 文件)中

静态库由程序ar 生成,lib 为前缀 .a 为后缀

生成静态链接库

生成静态库需要先对源文件进行汇编 ,(使用参数-c)得到二进制格式的目标文件(-o)然后通过参数 ar 将目标文件进行打包。
ar 有三个参数:

  • c 创建一个库 ,不管库存不存在,都进行创建。
  • s 创建目标文件索引
  • r 在库中插入模块(替换),默认新的成员添加在库的结尾处,如果模块名在库中已经存在,则替换原来文件。
    #准备源文件.c
    #编译成二进制文件
    $ gcc -c add.c sub.c
    #创建静态库
    $ ar rcs 静态库的名字(libxxx.a) 原材料 (.o)

动态库

动态库是一种在运行时被加载的库。其文件格式为 .so(Shared Object)。

直接用gcc 命令,添加 -fPIC(在汇编的时候不是简单的 -c ) -shared 以.so 为后缀。

生成动态链接库

#生成与位置无关的代码
$ gcc 源文件(*.c) -c -fPIC -I 指定头文件路径
# 把生成的目标文件.o 打包生成动态库
$ gcc -shared 与位置无关的目标文件(*.o) -o 动态库(libxx.so)

不管是静态库还是动态库,在用gcc 和源文件.c 的时候,一般都会使用到头文件,一般都需要指明头文件路径

指定动态库路径

  • 使用环境变量

    export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH

    /path/to/lib 是动态库所在目录

    $LD_LIBRARY_PATH 用于保留之前的路径配置

    等号两边不能有空格

  • 配置文件/etc/ld.so.conf

    #编辑
    sudo vi /etc/ld.so.conf
    #将动态库的路径写入
    /path/to/lib
    #更新动态连接器缓存
    sudo ldconfig
    #运行文件
    ./my_program

git

安装之后进行配置

git config --global user.name "Your Name"
git config --global uers.email "Your Email"

创建版本库

版本库就是仓库,目录。里面所有文件都可以被git 管理

  • 创建版本库以及初始化
#创建一个新库
mkdir newrepository
#将其编程git 可以管理的仓库
git init

  • 把文件添加到版本库(假设我已经写好了一个readme.txt 的文件)

    git add readme,txt
    git commit -m "wrote a readme file"



    第一步,用git add 告诉git 将文件添加到仓库中

    第二部,用git commit 告诉git将文件提交到仓库 -m

    commit 可以一次提交多个文件,可以add 多个文件之后,一次性将提交

    添加文件的时候 注意文件和git 命令都是在git仓库(目录)下

时光机穿梭

  • 更改文件之后

    #可以查肯当前仓库的状态(会告诉我们什么被修改了)
    git status
    #如果想看修改了什么内容
    git diff readme.txt
    #提交,仍是两个操作
    git add readme.txt
    git commit -m <message>


  • 版本回退

    #查看所有的版本记录
    git log
    #使用git reset 命令回到上一个版本
    git reset --head HEAD^

    每一个版本都是有commit id 的

    git log --pretty=oneline
    1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
    e475afc93c209a690c39c13a46716e8fa000c366 add distributed
    eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file

    在git 中,我们用head 表示当前版本。

    上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

    --hard参数有啥意义?--hard会回退到上个版本的已提交状态,而--soft会回退到上个版本的未提交状态,--mixed会回退到上个版本已添加但未提交的状态。

    当我们回退版本之后又想恢复,一定是要找到commit id 的

    #git reflog 用来记录每一次命令
    git reflog
  • 撤销修改

    场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。

    场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。

    git reset 可以回退版本也可以把暂存区的修改回退到工作区

    场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,版本回退,不过前提是没有推送到远程库。

  • 删除文件

    一般情况下,我们手动使用rm 直接就删除了,但是git 的版本库会和工作区不一致。所以还需要从版本库中进行删除并提交。

    git add test.txt
    rm test.txt
    git rm test.txt
    git commit -m <message>

    如果删错了,因为版本库中仍存在,能够将其恢复

    git checkout -- test.txt

远程仓库

创建ssh key

ssh-keygen -t rsa -C "youremail"

可以在用户主目录中找到.ssh 里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人

  • 添加远程库

    GitHub 中创建同名库,而后在自己的本地仓库下运行命令,将其关联

    git remote add origin git@github.com:用户名/库名.git

    添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

    将本地库中的所有文件推送到远程库上

    git push -u origin master

    第一次进行推送master 的时候需要加上-u 之后就不用再加-u

  • 删除远程库

    #查看远程库消息
    git remote -v
    #根据名字进行删除
    git remote rm origin
  • 从远程库中克隆

    git clone git@github.com:名字/库名.git

分支管理

  • 创建与合并分支

    Git鼓励大量使用分支:

    查看分支:git branch

    会列出所有的分支,当前分支前会有* 号

    创建分支:git branch <name>

    切换分支:git checkout <name>或者git switch <name>

    创建+切换分支:git checkout -b <name>或者git switch -c <name>

    合并某分支到当前分支:git merge <name>

    删除分支:git branch -d <name>

  • 解决冲突

    当有多个分支对同一个文件进行处理,合并的时候会有冲突。

    需要手动解决冲突,在有冲突的文件中进行修改,之后再提交。

    然后删除分支


makefile

规则

target1,target2,target3...:depend1,depend2,depend3...
command

每一条规则是由三个部分组成:目标,依赖,命令

  • 命令:当前规则的动作,一般情况下这一个动作就是一个shell 命令。动作可以是多个,每个都占据一行。要缩进

    必须是tab 开始的缩进,不能是空格

  • 依赖

  • 目标: 在执行规则中生成与目标同名的文件,可以有多个目标,如果只执行命令,不生成目标文件,那么这样的目标称之伪目标

    把默认执行的放在第一行,其他的无所谓顺序


工作原理

在调用 make 命令编译程序的时候,make 会首先找到 Makefile 文件中的第 1 个规则,分析并执行相关的动作。

# makefile
# 规则之间的嵌套
# 规则1
app:a.o b.o c.o
gcc a.o b.o c.o -o app
# 规则2
a.o:a.c
gcc -c a.c
# 规则3
b.o:b.c
gcc -c b.c
# 规则4
c.o:c.c
gcc -c c.c

知识点拓展:
如果想要执行 makefile 中非第一条规则对应的命令, 那么就不能直接 make, 需要将那条规则的目标也写到 make的后边, 比如只需要执行规则3中的命令, 就需要: make b.o。

make 命令执行的时候会根据文件的时间戳判定是否执行makefile文件中相关规则中的命令。

  • 目标是通过依赖生成的,因此正常情况下:目标时间戳 > 所有依赖的时间戳, 如果执行 make
    命令的时候检测到规则中的目标和依赖满足这个条件, 那么规则中的命令就不会被执行。

  • 当依赖文件被更新了, 文件时间戳也会随之被更新, 这时候 目标时间戳 < 某些依赖的时间戳, 在这种情况下目标文件会通过规则中的命令被重新生成。

  • 如果规则中的目标对应的文件根本就不存在, 那么规则中的命令肯定会被执行。

伪目标

用来指定不对应实际文件的目标。通常用于执行特定的任务。clean intall test

因为make 是根据时间戳来决定任务是否执行。所以,将其设成伪目标,(伪目标不会被当作文件处理, 无论是否存在名为 clean 的文件,make clean 都会始终执行。)

.PHONY: clean
clean:
rm -f m.txt
rm -f x.txt

执行多条命令

把多条命令以;分隔,写到一行


cd_ok:
pwd; cd ..; pwd;

可以使用\把一行语句拆成多行,便于浏览

cd_ok:
pwd; \
cd ..; \
pwd

另一种执行多条命令的语法是用&&,它的好处是当某条命令失败时,后续命令不会继续执行:

cd_ok:
cd .. && pwd

变量

makefile 的变量分为三种,自定义变量,预定义变量和自动变量

自定义变量:

创建变量名并进行赋值,在需要的时候用$ 取出

变量名 =  变量值
obj = add.o div.o mainn.o sub.o
$(obj)

#这是一个规则,普通写法
calc:add.o div.o main.o mult.o sub.o
gcc add.o div.o main.o mult.o sub.o -o calc

#这是一个规则,里边使用了自定义变量
obj=add.o div.o main.o mult.o sub.o
target=calc
$(target):$(obj)
gcc $(obj) -o $(target)

自动变量

makefile 的规则语句中会出现目标文件和依赖路径,自动变量用来表示在指令中的目标文件和依赖文件

变量 含义
$+ 表示所有依赖文件
$< 第一个依赖文件
$^ 依赖项中,所有不重复的依赖文件
$ @ 表示目标文件,包含文件的拓展名
$* 表示目标文件,不包含文件的拓展名 ,可能有重复文件

模式匹配

#模式匹配 -> 通过一个公式, 代表若干个满足条件的规则
依赖有一个, 后缀为.c, 生成的目标是一个 .o 的文件, % 是一个通配符, 匹配的是文件名
%.o:%.c
gcc $< -c

函数

makefile中有很多函数并且所有的函数都是有返回值的。makefile中函数的格式和C/C++中函数也不同,其写法是这样的: $(函数名 参数1, 参数2, 参数3, …),主要目的是让我们能够快速方便的得到函数的返回值。
两个 makefile 中使用频率比较高的函数:wildcard和patsubst。

wildcard

这个函数的目标作用是获取指定目录下指定类型的文件名,返回值是以空格分隔的,指定目录下的所有复合条件的文件名列表

#该函数的参数只有一个, 但是这个参数可以分成若干个部分, 通过空格间隔
$(wildcard PATTERN...)
参数: 指定某个目录, 搜索这个路径下指定类型的文件,比如: *.c



#使用举例: 分别搜索三个不同目录下的 .c 格式的源文件
src = $(wildcard /home/robin/a/*.c /home/robin/b/*.c *.c) # *.c == ./*.c
#返回值: 得到一个大的字符串, 里边有若干个满足条件的文件名, 文件名之间使用空格间隔
/home/robin/a/a.c /home/robin/a/b.c /home/robin/b/c.c /home/robin/b/d.c e.c f.c

patsubst

按照特定模式替换指定文件名的后缀

#有三个参数, 参数之间使用 逗号间隔
$(patsubst <pattern>,<replacement>,<text>)
% % $()

用户和群组管理

根用户(root)超级用户:
最高权限,对系统进行任何操作。root 用户的用户数据储存在/root 下
系统用户:
用系统或者相关程序创建,用于执行服务等系统任务。不能随意删除。
普通用户:
对自己的家目录下的文件进行操作,所有普通用户的家目录都在 /home/ 下,位于 /home/username/ 的位置,其中 username 是用户名。普通用户无法直接修改系统配置,也无法为系统环境安装或卸载软件。在Linux系统中,创建用户账户的同时也会创建一个与用户同名的群组,该群组是用户的主群组。

root用户的UID为0:系统用户的UID从1到999;普通用户的UID可以在创建时由管
理员指定,如果不指定,用户的UID默认从1000开始顺序编号。

用户登录过程

  • 查找用户信息:在 /etc/passwd 中确认用户名是否存在,并读取 UID、GID、家目录和默认 Shell。(用vim 或者cat 打开文件)
    larissa:x:1001:1001::/home/larissa:/bin/bash
    larissa:用户名。
    x:密码(这里为占位符,实际密码在 /etc/shadow 文件中)。
    1001:用户 ID(UID)。
    1001:组 ID(GID)。
    /home/larissa:用户的家目录。
    /bin/bash:默认 Shell 程序。
  • 验证密码:在 /etc/shadow 中找到该用户的加密密码,与用户输入的密码进行匹配。这个密码只有root 有权利访问
  • 启动 Shell:密码验证通过后,系统会进入用户家目录,并启动默认的 Shell 环境,使用户可以开始操作系统。

新建用户过程

useradd (以root 身份 或者sudo)
用于创建新用户可以指定用户的 UID、GID、主目录、Shell、附属群组等详细信息。常见的选项包括:

选项 含义
-u 指定用户的 UID。
-g 指定用户的主群组
-G 指定用户的附属群组(可以有多个群组,用逗号分隔
-d 指定用户的主目录路径。
-s 指定用户的登录 Shell
-p 设置用户的加密密码。
-f 设置账户过期后多少天禁用用户账户,-1 表示账户永不过期。
-m 创建用户的主目录。
-M 不创建用户的主目录。

-p 后的密码应为哈希:理想情况下,-p 后面应该是已经加密的密码,而不是明文密码
密码的设置:推荐先使用 useradd 创建用户,再使用 passwd user3 来设置密码,这样密码会被加密存储。

[root@server1 ~]# useradd -u 1010 -d /home/user3 -s /bin/bash -p 123456 -f -1 user3

系统在账户创建过程
在 /etc/passwd 里面建立一行与帐号相关的资料,包括建立 UID/GID/家
目录等;
在 /etc/shadow 里面将此帐号的密码相关参数填入,但是尚未有密码;
在 /etc/group 里面加入一个与帐号名称一模一样的群组名称;
在 /home 底下建立一个与帐号同名的目录作为使用者家目录,且权限为
700

  • id 查看用户的UID、GID和用户所属群组的信息,如果不指定用户,则显示当前用户的
    相关信息。命令格式:id
  • whoami 查看当前用户名
  • w 查看当前登录系统用户和详细信息

设置 password

超级用户可以为自己和其他用户设置口令,而普通用户只能为自己设置口令

passwd [选项] [username]

如果不指定 username,则默认修改当前用户的口令。

选项 含义
-l 锁定用户账户,禁止用户登录
-u 解锁之前被锁定的用户账户。
-d 将用户口令设置为空,允许用户在不输入口令的情况下登录,但这种情况下安全性较低
-f 强制用户在下次登录时必须修改口令。
-n 设置口令的最短存活期,指定用户在修改口令后,最少要保持该口令的天数。
-x 设置口令的最长存活期,超过这个天数用户必须更改口令
-w 在口令到期前多少天发出警告。
-i 指定口令过期后多少天账户会被停用。
-s 显示账户口令的简短状态信息。
echo "3279416" | passwd --stdin larissa

超级用户修改自己的口令:作为root用户,可以直接执行 passwd 命令来修改自己的口令。
超级用户修改其他用户的口令:例如,使用 passwd user1 修改用户 user1 的口令,不需要输入 user1 的原口令。
普通用户修改口令:普通用户执行 passwd 命令时,系统会要求输入原口令,以验证身份。

修改用户账户 usermod

root 用户更改所有,自己更改自己的

选项 含义
-c 设置或修改用户的备注信息,这通常用于描述用户的用途或身份。
-d 指定用户的新主目录。结合 -m 参数使用时,会将旧的主目录中的数据自动迁移到新的主目录中。
-e 设置账户到期的日期,格式为 YYYY-MM-DD。到期后用户将无法登录。
-g 修改用户的主群组。
-G 修改用户的扩展群组,可以将用户添加到多个群组,群组之间用逗号分隔。
-L 锁定用户,禁止其登录系统。用户被锁定后,无法使用账户登录。
-U 解锁用户,允许其登录系统。
-s 修改用户的默认登录 shell,例如,可以将其改为 /bin/tcsh
-u 修改用户的 UID(用户标识符),该 UID 必须是唯一的。

删除用户账户 userdel

# 删除用户, 添加参数 -r 就可以一并删除用户的家目录了
$ sudo userdel 用户名 -r

禁用和恢复用户账户

在前面的passwd 和usermod 中有各自的禁用与恢复方法,手动修改/etc/passwd 也能禁用
在前面加上 *\ 即可

群组有关操作

管理员(root)用户下操作,或者在普通用户下借助管理员权限完成该操作。

#添加与删除 
$ sudo groupadd 组名
$ sudo groupdel 组名

#修改 groupmod -g 修改GID -n 修改组名
$ sudo groupmod

#在组群中添加用户 gpasswd (root 群管理员可以进行操作)
#-a 将用户添加到指定的组中
#-d 将用户从指定的组中删除
#-r 取消群组的密码
#-A 指定群组的管理员
$sudo gpasswd - -a 人 组名

初始组群与有效组群
初始群组:创建用户时,系统为其分配一个初始群组(通常是与用户名相同的群组),该群组的GID是用户的主群组。
有效群组:用户可以加入多个附属群组,拥有这些群组的权限。在创建文件时,文件的群组将默认为用户当前有效群组。
查看有效组群与切换组群: groups newgrp

切换用户

用户切换需要使用su或者su -。使用su只切换用户, 当前的工作目录不会变化, 但是使用 su -不仅会切换用户也会切换工作目录, 工作目录切换为当前用户的家目录。
从用户A切换到用户B, 如果还想再切换回用户A,可以直接使用 exit。

#只切换用户, 工作目录不变
$ su 用户名
# 切换用户和工作目录, 会自动跳转到当前用户的家目录中
$ su - 用户名
#回到原来的用户
$ exit

给普通用户添加sudo

#1. 切换到root用户
$ su root
Password: # 输入root用户的密码

#2. 修改文件权限, 暴力一点没有关系, 反正还需要改回去, 直接 777 就行
$ chmod 777 sudoers

#3. 使用 vim 打开这个文件
$ vim sudoers

#4. 在文件中找到这一行, 在文件偏尾部的位置
root ALL=(ALL) ALL

#5. 照葫芦画瓢, 在下边新添加一行内容如下:
root ALL=(ALL) ALL # 原来的内容
sanji ALL=(ALL) ALL # 新添加的行, 将用户名指定为 sanji 即可

#6. 保存退出 (先按esc, 然后输入 :wq)
#7. 将文件改回原来的权限
$ chmod 400 sudoers

批量创建用户与修改用户密码

$ newusers userlist.txt
$ cat mima | chpasswd

进程

概念

  • 进程 (Process) 是一个程序在其虚拟地址空间中的一次执行活动。
  • 程序 是静态的代码和指令集合,而进程是动态的、具有生命周期的实体。
  • 一个程序可以产生多个进程,例如打开多个浏览器窗口。

特点:

  • 每个进程都有独立的地址空间。
  • 进程是系统资源分配的基本单位,如内存、CPU时间、I/O设备等。
  • 进程之间可以通过 进程间通信 (IPC) 相互交互。

程序只是一个静态的指令集合;而进程是一个程序的动态执行过程,它具

有生命期,是动态的产生和消亡的。

程序和进程无一一对应的关系。一方面一个程序可以由多个进程所共用,

即一个程序在运行过程中可以产生多个进程;另一方面,一个进程在生命

期内可以顺序的执行若干个程序。

进程在运行过程中可能有以下状态:

  • **就绪 (Ready)**:进程已分配必要资源,等待 CPU 调度。
  • **运行 (Running)**:进程正在 CPU 上执行。
  • **阻塞 (Blocked)**:进程因等待 I/O 或其他资源暂时停止。
  • **终止 (Terminated)**:进程完成任务或被杀死。

Linux 的多任务

Linux 是一个 多用户多任务系统,通过 分时技术 实现多任务:
CPU 按时间片轮流为多个任务服务,每个任务只执行几毫秒后切换。
进程切换对用户透明,看起来像是多个任务同时运行

进程 从执行它的用户处继承UID GID 从而决定对文件系统的存取和访问

linux 中的进程标志

  • PID (process ID ) 进程的唯一标识号

    系统启动后的第一个进程是init PID 是1

    init 是唯一一个由系统内核直接运行的进程

    除了init 之外,每个进程都有父进程(ppid)

  • PPID (parent process ID) 父进程的pid

  • UID/GID:

    • RUID 和 RGID:运行进程的用户和组。

      作用: 识别正在运行此进程的用户和组

    • EUID 和 EGID:访问文件和系统资源时的有效用户和组。

      确定一个进程对其访问的文件的权限

      如果没有设置 SUID 或 SGID:

      • 进程的 EUID 和 RUID 相同,EGID 和 RGID 相同。
      • 进程的权限由当前登录用户决定。

      如果文件设置了 SUID 或 SGID:

      • SUID:进程的 EUID 被设置为文件所有者的 UID。
      • SGID:进程的 EGID 被设置为文件所属组的 GID。

进程类型

交互进程:用户通过 Shell 启动的进程,可以是前台或后台进程。

批处理进程:无交互,提交到等待队列中按顺序运行。

**守护进程 (Daemon)**:

  • 在后台长期运行,为系统提供服务。

    在linux 启动时初始化,需要的时候运行于后台的进程

进程的启动方式

前台进程

是直接在中终端中运行的任务。

特点:

  • 运行的时候会占据终端,控制着输入输出(键盘与屏幕)
  • 运行期间,用户无法在终端中进行其他操作
  • 运行结束之后,shell 变成可用状态
$ sleep 10

sleep 10 是一个前台任务,他会占据终端10 秒,期间无法输入其他命令

后台进程

是在终端中启用但是不占用终端的输入输出(屏幕与键盘)

特点:

  • 用户在启用进程之后仍然能够使用终端输入其他命令
  • 需要在命令末尾加上 & 符号,将任务放到终端
  • 终端会显示后台任务的任务号 与**进程ID **
$ sleep 10 &
[1] 12345

[1] 是任务号,12345 是PID

如果忘记在命令后面加上&

  • 可以用Ctrl + Z 暂停当前任务

  • 用bg命令将暂停的任务放到后台运行

一个终端中只能同时存在一个前台,多个后台

启动进程

手动方式:前面两种例子

调度方式:按照预先指定的时间执行

  • at 命令

    用于在未来某个时间运行一次任务

    at 16:00
    at> echo "hello world" > output.txt
    at> <Ctrl+D>
  • batch 命令

    用于在系统负载较低的时候运行

    batch
    at> echo "message" > output.txt
    at> <Ctrl+D>
  • cron 命令

    用于周期性的运行任务,适合定时执行任务

    编辑定时任务:

    crontab -e

    添加任务

    0 4 * * * /path/to/script.sh  
    #每天凌晨 4 点运行 script.sh

进程管理

查看进程

ps 查看进程状态信息

选项 含义
-e/-A 显示所有进程
-f 完全显示。包含用户名,父进程
-u 显示指定用户的进程
-x 显示无终端控制的进程
-a 显示终端上的所有进程,包括其他用户地进程
-o 自定义输出

示例:

  • 查看所有进程:ps -e
  • 查看当前用户进程:ps aux
  • 自定义输出列:ps -o pid,ppid,user,comm

常见输出字段解释

字段 描述
UID 用户 ID,表示运行该进程的用户
USER 用户名,UID 的对应名字
PID 进程 ID,用于唯一标识一个进程
PPID 父进程的 ID
STAT/S 进程状态(见下方详细状态解释)
CMD 启动该进程的命令
TIME 该进程使用 CPU 的总时间
%CPU 进程占用的 CPU 百分比
%MEM 进程占用的内存百分比
TTY 启动进程的终端设备
RSS 进程实际占用的内存大小(以 KB 为单位)
VSZ 进程的虚拟内存大小(以 KB 为单位)
NI Nice 值,表示进程优先级的调整值

STAT 列(进程状态)解释

  • R: 正在运行或准备运行。
  • S: 休眠状态,等待某个事件完成(常见)。
  • T: 停止或暂停。
  • D: 不可中断的休眠状态(通常由于 I/O)。
  • Z: 僵尸进程,已结束但未被父进程回收。
  • X: 已死进程(几乎不会出现)。
  • <: 高优先级进程。
  • N: 低优先级进程

搜索进程

#查找包含httpd 的行
ps aux | grep httpd

root 1234 0.0 0.1 123456 1234 ? Ss 10:00 0:00 /usr/sbin/httpd
apache 2345 0.1 0.2 234567 2345 ? Sl 10:01 0:01 /usr/sbin/httpd
#查找名称完全匹配 httpd 的进程,并显示详细信息。
ps -fp $(pgrep -d, -x httpd)
UID PID PPID C STIME TTY TIME CMD
root 1234 1 0 10:00 ? 00:00:00 /usr/sbin/httpd
apache 2345 1234 0 10:01 ? 00:00:01 /usr/sbin/httpd

#查找名称包含httpd 的所有进程ID
pgrep httpd
1234
2345
#查找名称为 httpd 的所有进程 ID(简化版)
pidof httpd
1234 2345

注销之后继续运行进程

nohup 命令 [选项] [参数] [输出文件] &

优先权

这个值的范围是-20到19,默认是0

值越小说明对CPU的使用越优先查看

进程优先级(看NI列的值)

• ps-l

• ps-o comm,nice

改变优先权

  • 在启动进程时修改

    nice -优先级改变量 命令 [&]

    若为正,表示增加nice值,即降低进程优先权

    u若为负,表示减小nice值,即提高优先权

    u若缺省,则默认为10,即nice值增加10

  • 在进程运行中调整

    在系统资源紧张时,可以通过降低其他不着急的进程的优先权,让别的进程分到更多的cpu 时间

    root 可以提高进程的优先权,其他用户没有权力

    renice 优先级 [-p pid] [-u user] [-g gid]
    renice 5 -p 2345

    普通用户一旦增加某个进程的优先级(减低优先值)后,就无法再恢复到原来的优先级

进程信号

是一种软件层次上的中断机制,允许操作系统或其他进程与某个进程进行交互。

信号可以在进程之间直接发送,无需用户干预,是最基本的进程间通信方式之一

常见信号类型

  • SIGTERM (15)

    正常终止信号。

    默认的进程终止信号,可以被进程捕获或忽略。

  • SIGKILL (9)

    强制终止信号。

    无法被捕获或忽略,用于强制杀死进程。

  • SIGHUP (1)

    终端挂起信号。

    通常用来让守护进程重新加载配置文件

查看所有信号

$ kill -l

列出所有支持的信号以及对应的数字编号

发送信号

  • 通过kill 发送信号

    #按照PID发送信号
    $ kill [信号] PID
    $ kill -9 1234 #强制杀死进程1234
    #默认信号为sigterm
    $ kill 1234

  • 通过killall 命令

    #按照名称种植所有匹配的进程
    $ killall [信号] 进程名
    $ killall -9 myprog #杀死所有名为myprog 的进程
  • 通过pkill 命令

    #按照模式匹配进程名
    $ pkill [-信号] 模式
    $ pkill -HUP apache2#给所有名为 apache2 的进程发送 SIGHUP 信号

信号数字和名称可以互换

$ kill -9 1234
$ kill -SIGKILL 1234

杀死进程

为什么杀死进程

资源占用:进程占用过多 CPU 或内存资源。

锁定终端:导致用户无法运行其他任务。

长时间运行:任务没有预期效果且无法正常退出。

意外输出:产生过多屏幕或磁盘输出,影响系统性能

命令:

  • kill

    kill 1234
    kill -9 1234
  • killall

    kill -9 apache2
  • pkill

    pkill -SIGTERM  myscrip

发送信号与杀死进程的区别?

发送信号 是一种更灵活的方式,可以控制进程的行为或状态(例如暂停、恢复、终止)。

杀死进程 是信号的特殊应用,通过发送 SIGKILL 信号,强制终止进程,适合处理无响应的进程。

推荐优先使用 SIGTERM 等友好信号,只有在进程无法正常终止时,才使用 SIGKILL。

作业控制

定义

  • 作业控制是指管理当前用户正在运行的进程行为,包括暂停、恢复或终止任务。
  • 常见操作由 Shell 提供,如 jobs、fg 和 bg。

常用命令

  • 暂停作业 Ctrl+z

    sleep 100
    Ctrl + z
  • 列出作业 jobs 查看当前用户的后台作业

    jobs

  • 恢复作业

    #后台恢复运行
    bg [%作业号]
    #前台恢复运行
    fg [%作业号]
  • 终止作业

    kill %1

辨析:

作业和进程的区别

特性 作业 (Job) 进程 (Process)
定义 用户通过 Shell(或其他接口)提交的一组任务,可以是一个或多个进程的集合。 进程是一个正在运行的程序实例,具有唯一的 PID。
管理单元 作业是一个用户层面的概念,主要用于用户与 Shell 的交互管理。 进程是操作系统管理的最小单位,通过内核进行调度和管理。
标识方式 用 作业号 标识,作业号是由 Shell 分配的,与用户相关。 用 进程号 (PID) 标识,PID 是全局唯一的。
范围 一个作业可以包含多个进程。 每个进程是独立的,不与其他进程共享标识。
用途 用户可以通过 jobs、fg、bg 等命令管理作业。 系统通过 PID 管理进程,可以使用 ps、kill 等命令操作。

发送信号与作业控制的区别

属性 发送信号 作业控制
适用范围 可针对系统中任何进程(通过 PID)进行操作。 仅限于当前 Shell 会话中启动的作业(作业号 %N)。
操作机制 直接使用信号机制(如 SIGSTOP, SIGCONT 等)。 基于信号机制,但提供更高层的命令接口。
控制单位 针对进程(通过 PID 识别)。 针对作业(通过作业号 %N 识别)。
常用命令 kill, killall, pkill 等。 jobs, fg, bg, kill 等。
应用场景 灵活控制任何进程,无需与 Shell 会话绑定。 管理当前 Shell 会话中的前台和后台作业。

管理守护进程

命令:

  • 启动与停止服务

    $ systemctl start <服务名>
    $ systemctl stop <服务名>

  • 查看服务状态

    $ systemctl status <服务名>

  • 设置服务开机启动

    $ systemctl enable <服务名>

bash shell

正则表达式

sed 编译器

按行处理数据,适合添加、删除、替换整行内容


sed [选项] '<script>' 文件名

其中,<script> 是指 sed 脚本,用来定义要进行的操作。常见选项包括:

  • -e:直接在命令行中指定 sed 脚本。
  • -f:从文件中读取 sed 脚本。
  • -n:安静模式,仅输出经过处理的内容。
  • -i:直接修改文件内容(谨慎使用)

常用的操作命令

  • a:在指定行后添加新行。
  • c:替换指定行。
  • d:删除指定行。
  • i:在指定行前插入新行。
  • p:打印指定行内容。搜索并打印
  • s:搜索并替换。
  • g : 全局替换

一般打印输出的时候需要使用 -n

#删除2到5行
nl /etc/passwd | sed '2,5d'
#在2行后添加新行
nl /etc/passwd | sed '2a Hello World'
#在2行前添加新行
nl /etc/passwd | sed '2i Hello World'
#替换
nl passwd | sed '2,5c No 2-5 number'
#将root 替换
nl /etc/passwd | sed 's/root/sroot/g'
#搜索并显示
nl /etc/passwd | sed -n '/root/p'
nl /etc/passwd | sed '/root/d'
nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p;q}'
sed -i 's/\.$/\!/g' regular.txt

在 sed 中,通过这种模式 /pattern/{commands},可以使 {} 中的命令仅作用于匹配该模式的行,而不匹配的行则跳过。

awk

awk '条件 { 动作 }' 文件名

条件:可以是任意表达式,满足该条件的行会执行 {} 内的动作。

动作:对满足条件的行执行的操作,通常是打印、计算等

处理流程:

awk 读入文件的每一行,将整行存储在 $0,并根据分隔符将每个字段存入 $1, $2, ...。

检查是否符合条件。

如果符合条件,执行 {} 中的动作。

对每一行重复以上步骤,直到文件结束。

常用内建变量

  • **NF**:表示当前行的字段总数。例如 NF=3 表示这一行有3个字段。

  • **NR**:表示当前处理的行号。

    **FS**:指定分隔符,默认是空格或Tab。

shell

在 Shell 编程中,控制流语句 if、while、for、until、break 和 continue 用于控制脚本的执行流程。下面是它们的用法和一些示例。

1. if 条件语句

用于条件判断,根据判断结果执行不同的代码块。

语法:

bashCopy codeif [ 条件 ]; then
#条件为真时执行
elif [ 条件 ]; then
#另一个条件为真时执行
else
#其他情况执行
fi

示例:

bashCopy code#!/bin/bash

num=10
if [ "$num" -gt 5 ]; then
echo "num 大于 5"
elif [ "$num" -eq 5 ]; then
echo "num 等于 5"
else
echo "num 小于 5"
fi

2. while 循环

while 循环在条件为真时重复执行代码块。

语法:

bashCopy codewhile [ 条件 ]; do
#循环的代码块
done

示例:

bashCopy code#!/bin/bash

counter=1
while [ "$counter" -le 5 ]; do
echo "Counter: $counter"
counter=$((counter + 1))
done

3. for 循环

用于遍历列表或指定范围内的数字。

语法:

bashCopy codefor 变量 in 列表; do
#循环的代码块
done

示例:

bashCopy code#!/bin/bash

for name in Alice Bob Carol; do
echo "Hello, $name!"
done

4. until 循环

until 循环在条件为假时重复执行代码块,和 while 循环相反。

语法:

bashCopy codeuntil [ 条件 ]; do
#循环的代码块
done

示例:

bashCopy code#!/bin/bash

counter=1
until [ "$counter" -gt 5 ]; do
echo "Counter: $counter"
counter=$((counter + 1))
done

5. break 语句

break 用于提前退出循环。

示例:

bashCopy code#!/bin/bash

for i in {1..10}; do
if [ "$i" -eq 5 ]; then
break #当 i 等于 5 时退出循环
fi
echo "Number: $i"
done

6. continue 语句

continue 用于跳过当前循环的剩余部分,直接进入下一次循环。

示例:

bashCopy code#!/bin/bash

for i in {1..10}; do
if [ "$i" -eq 5 ]; then
continue #跳过当前循环,当 i 等于 5 时跳过
fi
echo "Number: $i"
done

Shell 函数在编写脚本时能帮助分解任务,组织代码,并提高代码的可读性和可维护性。以下是每个概念的基本用法和示例。

1. Shell 函数的定义方法

定义函数的基本语法:

bashCopy codefunction_name() {
#函数的主体
}

或使用 function 关键字:

bashCopy codefunction function_name {
#函数的主体
}

示例:

bashCopy codegreet() {
echo "Hello, $1!"
}

2. Shell 函数的参数传递、调用和返回值

在 Shell 函数中,参数可以通过 $1、$2 等来访问,其中 $1 表示第一个参数,$2 表示第二个参数,依此类推。返回值通过 return 命令设定,但只能是整数值。

示例:

bashCopy codeadd() {
local sum=$(( $1 + $2 ))
echo $sum #通过 echo 返回结果
}

#调用函数
result=$(add 3 5)
echo "Result: $result"

返回状态(整数返回值):

bashCopy codecheck_positive() {
if [ $1 -gt 0 ]; then
return 0
else
return 1
fi
}

#使用返回状态
check_positive 10
if [ $? -eq 0 ]; then
echo "Positive"
else
echo "Non-positive"
fi

3. Shell 函数的递归调用方法

Shell 支持递归调用,但应小心使用以避免无限递归。递归通常在计算阶乘、斐波那契数列等算法中使用。

示例:计算阶乘

bashCopy codefactorial() {
if [ $1 -le 1 ]; then
echo 1
else
local prev=$(factorial $(( $1 - 1 )))
echo $(( $1 * prev ))
fi
}

#调用递归函数
result=$(factorial 5)
echo "Factorial of 5: $result"

4. Shell 函数的嵌套调用

嵌套调用是指在一个函数内调用另一个函数。Shell 支持嵌套调用,适合在复杂的逻辑中分解子任务。

示例:嵌套调用函数

bashCopy codeouter_function() {
echo "This is the outer function."
inner_function
}

inner_function() {
echo "This is the inner function."
}

#调用外部函数
outer_function

嵌套调用对于实现模块化代码结构非常有帮助,可以在不同的函数中完成各自的任务,再组合成完整的流程。