用户管理

创建用户

useradd

只是创建一个用户名,命令如下:

1
sudo useradd username

并没有在/home目录下创建同名文件夹,也没有创建密码,因此利用这个用户登录系统,是登录不了的,为了避免这样的情况出现,可以添加-m参数创建:

1
sudo useradd username -m

它会在/home目录下创建同名文件夹,然后利用sudo passwd username为指定的用户名设置密码。

adduser

这个命令实际是一个perl脚本,是useradd等类似底层命令的更友好的前端,它会用交互性的方式建立新用户,使用它可以指定新用户的家目录,登录密码,是否加密主目录等等,它会:

  1. 建立一个新目录作为家目录
  2. 建立同名新组
  3. 把用户的主要组设为该组(除非命令选项覆盖以上默认动作,比如–disall-homdirecry之类)
  4. 从/etc/SKEL目录下拷贝文件到家目录,完成初始化
  5. 建立新用户的密码
  6. 如果其存在的话,还会执行一个脚本
1
sudo adduser username

删除用户

通过userdel命令即可:

1
sudo userdel -r username
  • -r:删除/home/路径下的用户文件夹

添加root权限

/etc/sudoers

该文件只能由root用户处理,其中包含了root权限的具体信息,具体可以参见linux /etc/sudoers 文件说明,其中信息有:

1
2
3
4
5
6
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
  • root用户具有root权限

    • root用户可以在任何可能出现的主机名的系统中,在任何用户任何组中执行任何命令

    • 文件格式

      1
      2
      3
      # useralias (用户名) hostalias (可以从哪些机器登陆) = (用户:用户组)"以什么用户,什么组" cmndalias "执行什么命令"
      useralias hostalias = (username:group) cmndalias
      %FOO ALL = (ALL) NOPASSWD:ALL,!/usr/sbin/
      • NOPASSWD:ALL:不用输入密码执行任何命令
      • %:表示用户组
      • !:表示禁止执行
  • admin组和sudo组中的用户均具有root权限

    • 查看当前用户组:

      1
      id username
    • 添加到root权限组:

      1
      2
      3
      # usermod -a  -G group -s /bin/bash username
      usermod -a -G sudo -s /bin/bash username
      usermod -a -G admin -s /bin/bash username
    • 从指定组中移除用户:

      1
      gpasswd -d username group

/etc/sudoers.d/*

该文件夹下的内容和/etc/sudoers中的类似,通过如下方式可以添加root用户:

1
echo "username    ALL=(ALL) ALL" >> /etc/sudoers.d/username

压缩解压类

tar

1
tar [-cxtzjvfpPN] 文件与目录 ....

参数:

  • 压缩与解压(以下三个仅能存在一个,不能同时存在)
    • -c :建立一个压缩文件的参数指令(create)
    • -x :解开一个压缩文件的参数指令
    • -t :查看 tarfile 里面的文件
  • 压缩与解压类型
    • -z :是否同时具有 gzip 的属性?即是否需要用 gzip 压缩?(.tar.gz、.tgz)
    • -j :是否同时具有 bzip2 的属性?即是否需要用 bzip2 压缩?(.tar.bz2、.tar.bz)
  • -v :压缩的过程中显示文件
  • -f :使用档名,请留意,在 f 之后要立即接档名喔!不要再加参数
  • -p :使用原文件的原来属性(属性不会依据使用者而变)
  • -P :可以使用绝对路径来压缩
  • -N :比后面接的日期(yyyy/mm/dd)还要新的才会被打包进新建的文件中
  • –exclude FILE:在压缩的过程中,不要将 FILE 打包

范例:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
范例一:将整个 /etc 目录下的文件全部打包成为 /tmp/etc.tar
[root@linux ~]# tar -cvf /tmp/etc.tar /etc <==仅打包,不压缩!
[root@linux ~]# tar -zcvf /tmp/etc.tar.gz /etc <==打包后,以 gzip 压缩
[root@linux ~]# tar -jcvf /tmp/etc.tar.bz2 /etc <==打包后,以 bzip2 压缩
# 特别注意,在参数 f 之后的文件档名是自己取的,我们习惯上都用 .tar 来作为辨识。
# 如果加 z 参数,则以 .tar.gz 或 .tgz 来代表 gzip 压缩过的 tar file
# 如果加 j 参数,则以 .tar.bz2 来作为附档名
# 上述指令在执行的时候,会显示一个警告讯息:
# 『tar: Removing leading `/' from member names』那是关于绝对路径的特殊设定。

范例二:查阅上述 /tmp/etc.tar.gz 文件内有哪些文件?
[root@linux ~]# tar -ztvf /tmp/etc.tar.gz
# 由于使用 gzip 压缩,所以要查阅该 tar file 内的文件时,
# 就要加上 z 这个参数

范例三:将 /tmp/etc.tar.gz 文件解压缩在 /usr/local/src 底下
[root@linux ~]# cd /usr/local/src
[root@linux src]# tar -zxvf /tmp/etc.tar.gz
# 在预设的情况下,我们可以将压缩档在任何地方解开的!以这个范例来说,
# 我先将工作目录变换到 /usr/local/src 底下,并且解开 /tmp/etc.tar.gz ,
# 则解开的目录会在 /usr/local/src/etc ,另外,如果您进入 /usr/local/src/etc
# 则会发现,该目录下的文件属性与 /etc/ 可能会有所不同

范例四:在 /tmp 底下,我只想要将 /tmp/etc.tar.gz 内的 etc/passwd 解开而已
[root@linux ~]# cd /tmp
[root@linux tmp]# tar -zxvf /tmp/etc.tar.gz etc/passwd
# 我可以透过 tar -ztvf 来查阅 tarfile 内的文件名称,如果单只要一个文件,
# 就可以透过这个方式来下达!注意到! etc.tar.gz 内的根目录 / 是被拿掉了!

范例五:将 /etc/ 内的所有文件备份下来,并且保存其权限!
[root@linux ~]# tar -zxvpf /tmp/etc.tar.gz /etc
# 这个 -p 的属性是很重要的,尤其是当您要保留原本文件的属性时!

范例六:在 /home 当中,比 2005/06/01 新的文件才备份
[root@linux ~]# tar -N '2005/06/01' -zcvf home.tar.gz /home

范例七:我要备份 /home, /etc ,但不要 /home/dmtsai
[root@linux ~]# tar --exclude /home/dmtsai -zcvf myfile.tar.gz /home/* /etc

范例八:将 /etc/ 打包后直接解开在 /tmp 底下,而不产生文件!
[root@linux ~]# cd /tmp
[root@linux tmp]# tar -cvf - /etc | tar -xvf -
# 这个动作有点像是 cp -r /etc /tmp 啦~依旧是有其有用途的!
# 要注意的地方在于输出档变成 - 而输入档也变成 - ,又有一个 | 存在
# 这分别代表 standard output, standard input 与管道命令

其他常用类型

.tar
解包:tar xvf FileName.tar
打包:tar cvf FileName.tar DirName

.zip
解压:unzip FileName.zip
压缩:zip FileName.zip DirName

.rar
解压:rar x FileName.rar
压缩:rar a FileName.rar DirName

.gz
解压1:gunzip FileName.gz
解压2:gzip -d FileName.gz
压缩:gzip FileName

.tar.gz 和 .tgz
解压:tar zxvf FileName.tar.gz
压缩:tar zcvf FileName.tar.gz DirName

.bz2
解压1:bzip2 -d FileName.bz2
解压2:bunzip2 FileName.bz2
压缩: bzip2 -z FileName

.tar.bz2
解压:tar jxvf FileName.tar.bz2
压缩:tar jcvf FileName.tar.bz2 DirName

.bz
解压1:bzip2 -d FileName.bz
解压2:bunzip2 FileName.bz
压缩:未知

.tar.bz
解压:tar jxvf FileName.tar.bz
压缩:未知

.Z
解压:uncompress FileName.Z
压缩:compress FileName

.tar.Z
解压:tar Zxvf FileName.tar.Z
压缩:tar Zcvf FileName.tar.Z DirName

.lha
解压:lha -e FileName.lha
压缩:lha -a FileName.lha FileName

.rpm
解包:rpm2cpio FileName.rpm | cpio -div

.deb
解包:ar p FileName.deb data.tar.gz | tar zxf -

gzip 命令

语法:gzip [选项] 压缩(解压缩)的文件名

  • -c 将输出写到标准输出上,并保留原有文件
  • -d 将压缩文件解压
  • -l 对每个压缩文件,显示下列字段
    • 压缩文件的大小
    • 未压缩文件的大小
    • 压缩比
    • 未压缩文件的名字
  • -r 递归式地查找指定目录并压缩其中的所有文件或者是解压缩
  • -t 测试,检查压缩文件是否完整
  • -v 对每一个压缩和解压的文件,显示文件名和压缩比
  • -num 用指定的数字 num 调整压缩的速度,-1 或 --fast 表示最快压缩方法(低压缩比),-9 或–best表示最慢压缩方法(高压缩比)。系统缺省值为 6

硬件信息查询

内核和版本

1
2
3
uname -a
cat /etc/issue
cat /etc/redhat-release(针对redhat系列)

位数

1
2
3
4
5
6
7
# 通过字节长度区分
getconf LONG_BIT
getconf WORD_BIT
# 如果有x86_64就是64位的,没有就是32位的
uname -a
# 32-bit即是32位的 linux, 如是64位的, 显示的是 64-bit
file /sbin/init
  • 32位的系统中int类型和long类型一般都是4字节,64位的系统中int类型还是4字节的,但是long已变成了8字节
  • linux系统中可用"getconf WORD_BIT"和"getconf LONG_BIT"获得word和long的位数。64位系统中应该分别得到32和64

硬件信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 全部信息
dmidecode | more
# 型号
dmidecode | grep "Product Name"
# 网卡型号
lspci | grep Ethernet
# CPU信息
grep name /proc/cpuinfo
lscpu
# 内存信息
grep -P "MemTotal|SwapTotal" /proc/meminfo
grep -E "MemTotal|SwapTotal" /proc/meminfo
free -h
top
# 硬盘信息
df -h
fdisk -l
du -d 1 -h # -d:深度
1
2
3
4
# 需要提前安装 二选一即可
sudo apt install screenfetch neofetch
screenfetch
neofetch

后台运行

参考资料:Linux 守护进程的启动方法

后台执行

一般运行linux上的程序执行 .sh 文件(./sh文件)时都会影响当前CMD窗口的操作,如果需要后台运行则需要借助 nohup& 命令来实现。

1
nohup java -server -Xms128M -Xmx512M -XX:MetaspaceSize=128M -jar test.jar $1 $2 $3 &
  • nohup :加在一个命令的最前面,表示不挂断的运行命令
  • &:加在一个命令的最后面,表示这个命令放在后台执行

nohub做了以下:

  • 阻止SIGHUP信号发到这个进程。
  • 关闭标准输入。该进程不再能够接收任何输入,即使运行在前台。
  • 重定向标准输出和标准错误到文件nohup.out

注意,nohup命令不会自动把进程变为"后台任务",所以必要时需要加上&符号

查看后台

psjobs都可以用于查看后台程序:

  • jobs:只能查看当前终端后台执行的任务,换了终端就看不见了
  • ps:适用于查看瞬时进程的动态,可以看到别的终端的任务

jobs:

1
2
3
[root@localhost test]# jobs
[1]- 运行中 nohup java -Dfile.encoding=UTF-8 -Dname=Runtime-Name -server -Xms128M -Xmx512M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -jar test.jar $1 $2 $3 &(工作目录:/home/ams/ams-server/test)
[2]+ 运行中 nohup java -Dfile.encoding=UTF-8 -Dname=Container-Name -server -Xms128M -Xmx512M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -jar test1.jar $1 $2 $3 &
  • “+”:最近的一个任务(当前任务)
  • “-”:之前的任务

只有在当前命令行中使用nohup& 时,jobs命令才能将它显示出来。如果将他们写到 .sh 脚本中,然后执行脚本,是显示不出来的

ps:

这个是查看进程常用的命令,不多说了。

1
2
3
4
[root@localhost test]# ps -aux|grep java
root 21219 0.3 3.9 6258172 148900 pts/0 Sl 10:08 0:02 java -Dfile.encoding=UTF-8 -Dname=Runtime-Name -server -Xms128M -Xmx512M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -jar test.jar
root 21662 0.2 3.0 5041008 116648 pts/0 Sl 10:10 0:01 java -Dfile.encoding=UTF-8 -Dname=Container-Name -server -Xms128M -Xmx512M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -jar test1.jar
root 23761 0.0 0.0 112664 972 pts/0 S+ 10:19 0:00 grep --color=auto java
  • a:显示所有程序
  • u:以用户为主的格式来显示
  • x:显示所有程序,不以终端机来区分

关闭后台程序

kill 命令:

  • 通过jobs命令查看jobnum,然后执行kill %jobnum
  • 通过ps命令查看进程号PID,然后执行kill %PID

如果是前台进程的话,直接执行Ctrl+C就可以终止了

前后台切换

  • fg命令:将后台中的命令调至前台继续运行。如果后台中有多个命令,可以先用jobs查看jobnun,然后用fg %jobnum将选中的命令调出。

  • Ctrl + Z命令:将一个正在前台执行的命令放到后台,并且处于暂停状态

  • bg命令:将一个在后台暂停的命令,变成在后台继续执行

    如果后台中有多个命令,可以先用jobs查看jobnum,然后用 bg %jobnum 将选中的命令调出继续执行。

端口相关

查看端口

lsof

lsof命令(lists openfiles)用于查看进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。

在linux下,任何事物都以文件的形式存在,这其中包括各种网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统监测以及排错将是很有帮助的。

选项:

1
2
3
4
5
6
7
8
9
10
11
12
-a:列出打开文件存在的进程;
-c<进程名>:列出指定进程所打开的文件;
-g:列出GID号进程详情;
-d<文件号>:列出占用该文件号的进程;
+d<目录>:列出目录下被打开的文件;
+D<目录>:递归列出目录下被打开的文件;
-n<目录>:列出使用NFS的文件;
-i<条件>:列出符合条件的进程。(4、6、协议、:端口、 @ip )
-p<进程号>:列出指定进程号所打开的文件;
-u:列出UID号进程详情;
-h:显示帮助信息;
-v:显示版本信息。

查看端口号:

1
lsof -i:端口号

netstat

netstat命令用来打印Linux中网络系统的状态信息,可以得知整个Linux系统的网络情况

选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-a或--all:显示所有连线中的Socket;
-A<网络类型>或--<网络类型>:列出该网络类型连线中的相关地址;
-c或--continuous:持续列出网络状态;
-C或--cache:显示路由器配置的快取信息;
-e或--extend:显示网络其他相关信息;
-F或--fib:显示FIB;
-g或--groups:显示多重广播功能群组组员名单;
-h或--help:在线帮助;
-i或--interfaces:显示网络界面信息表单;
-l或--listening:显示监控中的服务器的Socket;
-M或--masquerade:显示伪装的网络连线;
-n或--numeric:直接使用ip地址,而不通过域名服务器;
-N或--netlink或--symbolic:显示网络硬件外围设备的符号连接名称;
-o或--timers:显示计时器;
-p或--programs:显示正在使用Socket的程序识别码和程序名称;
-r或--route:显示Routing Table;
-s或--statistice:显示网络工作信息统计表;
-t或--tcp:显示TCP传输协议的连线状况;
-u或--udp:显示UDP传输协议的连线状况;
-v或--verbose:显示指令执行过程;
-V或--version:显示版本信息;
-w或--raw:显示RAW传输协议的连线状况;
-x或--unix:此参数的效果和指定"-A unix"参数相同;
--ip或--inet:此参数的效果和指定"-A inet"参数相同。

例子:

1
2
3
4
netstat -a     #列出所有端口
netstat -at #列出所有tcp端口
netstat -au #列出所有udp端口
netstat -aptn #列出所有tcp端口以及程序名称和ip地址

检测远程端口

telnet

telnet命令用于登录远程主机,对远程主机进行管理。

参数:

  • 远程主机:指定要登录进行管理的远程主机;
  • 端口:指定TELNET协议使用的端口号。

选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-8:允许使用8位字符资料,包括输入与输出;
-a:尝试自动登入远端系统;
-b<主机别名>:使用别名指定远端主机名称;
-c:不读取用户专属目录里的.telnetrc文件;
-d:启动排错模式;
-e<脱离字符>:设置脱离字符;
-E:滤除脱离字符;
-f:此参数的效果和指定"-F"参数相同;
-F:使用Kerberos V5认证时,加上此参数可把本地主机的认证数据上传到远端主机;
-k<域名>:使用Kerberos认证时,加上此参数让远端主机采用指定的领域名,而非该主机的域名;
-K:不自动登入远端主机;
-l<用户名称>:指定要登入远端主机的用户名称;
-L:允许输出8位字符资料;
-n<记录文件>:指定文件记录相关信息;
-r:使用类似rlogin指令的用户界面;
-S<服务类型>:设置telnet连线所需的ip TOS信息;
-x:假设主机有支持数据加密的功能,就使用它;
-X<认证形态>:关闭指定的认证形态。

能够通过该命令间接访问某个端口是否开放:

1
telnet ip地址 端口号

nmap

nmap命令是一款开放源代码的网络探测和安全审核工具,它的设计目标是快速地扫描大型网络(包括端口号、状态以及对应的服务)。

参数:

  • ip地址:指定待扫描报文中的TCP地址。

选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-O:激活操作探测;
-P0:值进行扫描,不ping主机;
-PT:是同TCP的ping;
-sV:探测服务版本信息;
-sP:ping扫描,仅发现目标主机是否存活;
-ps:发送同步(SYN)报文;
-PU:发送udp ping;
-PE:强制执行直接的ICMPping;
-PB:默认模式,可以使用ICMPping和TCPping;
-6:使用IPv6地址;
-v:得到更多选项信息;
-d:增加调试信息地输出;
-oN:以人们可阅读的格式输出;
-oX:以xml格式向指定文件输出信息;
-oM:以机器可阅读的格式输出;
-A:使用所有高级扫描选项;
--resume:继续上次执行完的扫描;
-P:指定要扫描的端口,可以是一个单独的端口,用逗号隔开多个端口,使用“-”表示端口范围;
-e:在多网络接口Linux系统中,指定扫描使用的网络接口;
-g:将指定的端口作为源端口进行扫描;
--ttl:指定发送的扫描报文的生存期;
--packet-trace:显示扫描过程中收发报文统计;
--scanflags:设置在扫描报文中的TCP标志。

例子:

1
2
nmap 192.168.1.102 # 扫描对应ip的端口号开放情况以及对应的服务
nmap www.baidu.com -p 80 # 扫描指定端口

nc

nc命令是netcat命令的简称,都是用来设置路由器。

参数:

  • 主机:指定主机的IP地址或主机名称;
  • 端口号:可以是单个整数或者是一个范围。

选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-g<网关>:设置路由器跃程通信网关,最多设置8个;
-G<指向器数目>:设置来源路由指向器,其数值为4的倍数;
-h:在线帮助;
-i<延迟秒数>:设置时间间隔,以便传送信息及扫描通信端口;
-l:使用监听模式,监控传入的资料;
-n:直接使用ip地址,而不通过域名服务器;
-o<输出文件>:指定文件名称,把往来传输的数据以16进制字码倾倒成该文件保存;
-p<通信端口>:设置本地主机使用的通信端口;
-r:指定源端口和目的端口都进行随机的选择;
-s<来源位址>:设置本地主机送出数据包的IP地址;
-u:使用UDP传输协议;
-v:显示指令执行过程;
-w<超时秒数>:设置等待连线的时间;
-z:使用0输入/输出模式,只在扫描通信端口时使用。

例子:

1
2
3
nc -w 5  211.100.98.99 80 && echo ok ||echo no #判断对应端口是否开放
nc -v -w 1 192.168.228.222 -z 1-1000 # 扫描对应端口
nc -lp 1234 # 监听端口1234,监控传入的资料

开放指定端口

Ubuntu下,首先检测防火墙状态,如果打开需要开放指定端口:

1
2
sudo ufw status # 查询状态
sudo ufw allow 80 # 防火墙使能80端口

配置iptables,开放对应端口:

1
2
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT # 开放输入tcp的80端口
sudo iptables -L # 查看列表
  • iptables规则设置后是即时生效的,在机器重启后iptables中的配置信息会被清空

文本处理

Linux 操作文本的三大利器分别是 grep、sed 、awk,简称三剑客。

大师兄 awk:最擅长取列;二师兄 sed:最擅长取行;三师兄 grep:最擅长过滤。

awk

参考链接:AWK 官方手册Linux awk 命令awk实例一:简单入门AWK 简明教程

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。

之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

Awk通常被用来进行格式扫描和处理。通过扫描一个或多个文件中的行,查看是否匹配指定的正则表达式,并执行相关的操作。主要由以下特点:

  1. Awk以记录和字段的方式来查看文本文件
  2. 和其他编程语言一样,Awk 包含变量、条件和循环
  3. Awk能够进行运算和字符串操作
  4. Awk能够生成格式化的报表数据

Awk从一个文件或者标准输入中读取数据,并输出结果到标准输出

语法:

1
2
3
awk [选项参数] 'script' var=value file(s)

awk [选项参数] -f scriptfile var=value file(s)

工作方式

  1. Awk 一次读取文件中的一行
  2. 对于一行,按照给定的正则表达式的顺序进行匹配,如果匹配则执行对应的 Action
  3. 如果没有匹配上则不执行任何动作
  4. 在上诉的语法中, Search Pattern 和 Action 是可选的,但是必须提供其中一个
  5. 如果 Search Pattern 未提供,则对所有的输入行执行 Action 操作
  6. 如果 Action 未提供,则默认打印出该行的数据
  7. {} 这种 Action 不做任何事情,和未提供的 Action 的工作方式不一样
  8. Action 中的语句应该使用分号分隔

运算符

运算符 描述
= += -= *= /= %= ^= **= 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ 和 !~ 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加,减
* / % 乘,除与求余
+ - ! 一元加,减和逻辑非
^ *** 求幂
++ – 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员

内建变量

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 各文件分别计数的行号
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认值是%.6g)
OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS 输出记录分隔符(默认值是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)

用法

1
2
awk '/search pattern1/ {Actions}
/search pattern2/ {Actions}' file
  • search pattern是正则表达式
  • Actions 输出的语法
  • 在Awk 中可以存在多个正则表达式和多个输出定义
  • file 输入文件名
  • 单引号的作用是包裹起来防止shell 截断

关键字 BEGIN 和 END:

1
2
3
BEGIN { Actions}
{ACTION} # Action for everyline in a file Awk中的注释
END { Actions }
  • 在BEGIN 节中的 Actions 会在读取文件中的行之前被执行
  • 而END 节中的 Actions 会在读取并处理文件中的所有行后被执行

例子

创建一个包含下面内容的文本文件employee.txt

1
2
3
4
5
6
$cat employee.txt
100 Thomas Manager Sales $5,000
200 Jason Developer Technology $5,500
300 Sanjay Sysadmin Technology $7,000
400 Nisha Manager Marketing $9,500
500 Randy DBA Technology $6,000
  1. 默认的时候awk 打印文件中的每一行

    1
    2
    3
    4
    5
    6
    $ awk '{print;}' employee.txt
    100 Thomas Manager Sales $5,000
    200 Jason Developer Technology $5,500
    300 Sanjay Sysadmin Technology $7,000
    400 Nisha Manager Marketing $9,500
    500 Randy DBA Technology $6,000
  2. 打印匹配的行

    1
    2
    3
    4
    $ awk '/Thomas/
    > /Nisha/' employee.txt
    100 Thomas Manager Sales $5,000
    400 Nisha Manager Marketing $9,500
    • 每个组合 ( 正则表达式和对应的 Action) 必须用新行来分隔
  3. 仅打印指定的域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ awk '{print $2,$5;}' employee.txt
    Thomas $5,000
    Jason $5,500
    Sanjay $7,000
    Nisha $9,500
    Randy $6,000
    $ awk '{print $2,$NF;}' employee.txt
    Thomas $5,000
    Jason $5,500
    Sanjay $7,000
    Nisha $9,500
    Randy $6,000
    • $2 和 $5 分别代表名字和薪水
  4. 开始和最后的动作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ awk 'BEGIN {print "Name/tDesignation/tDepartment/tSalary";}
    > {print $2,"/t",$3,"/t",$4,"/t",$NF;}
    > END{print "Report Generated/n--------------";
    > }' employee.txt
    Name Designation Department Salary
    Thomas Manager Sales $5,000
    Jason Developer Technology $5,500
    Sanjay Sysadmin Technology $7,000
    Nisha Manager Marketing $9,500
    Randy DBA Technology $6,000
    Report Generated
    --------------
  5. 找出员工 ID 大于 200 的员工

    1
    2
    3
    4
    $ awk '$1 >200' employee.txt
    300 Sanjay Sysadmin Technology $7,000
    400 Nisha Manager Marketing $9,500
    500 Randy DBA Technology $6,000
  6. 打印技术部员工

    1
    2
    3
    4
    $ awk '$4 ~/Technology/' employee.txt
    200 Jason Developer Technology $5,500
    300 Sanjay Sysadmin Technology $7,000
    500 Randy DBA Technology $6,000
  7. 打印技术部门的员工数

    1
    2
    3
    4
    $ awk 'BEGIN { count=0;}
    $4 ~ /Technology/ { count++; }
    END { print "Number of employees in Technology Dept =",count;}' employee.txt
    Number of employees in Tehcnology Dept = 3

sed

参考链接:sed官方手册、、Linux sed命令sed 简明教程

sed全名叫stream editor,流编辑器,用程序的方式来编辑文本,基本上就是玩正则模式匹配。

工作方式

sed在处理时会把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。其伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
foreach line in file {
//放入把行Pattern_Space
Pattern_Space <= line;

// 对每个pattern space执行sed命令
Pattern_Space <= EXEC(sed_cmd, Pattern_Space);

// 如果没有指定 -n 则输出处理后的Pattern_Space
if (sed option hasn't "-n") {
print Pattern_Space
}
}
  • 注意-n参数

命令格式

1
2
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)

options选项如下:

  • -e<script>--expression=<script>:以选项中的指定的script(即后面的command)来处理输入的文本文件;
  • -f<script文件>--file=<script文件>:以选项中指定的script文件来处理输入的文本文件;
  • -h--help:显示帮助;
  • -n--quiet——silent:仅显示script处理后的结果;
  • -V--version:显示版本信息。
  • -i:直接修改文件内容

其中,command为处理对应文件的命令,几乎所有的命令都是这样的:

1
[address[,address]][!]{cmd}
  • address:可以是一个数字,也可以是一个模式,你可以通过逗号要分隔两个address 表示一个区间

  • !:匹配成功后是否执行命令

  • cmd:对应的命令,可以用正则表达式

    • cmd可以是多个,可以用分号分开,也可以用大括号括起来作为嵌套命令

    • cmd中可以使用正则表达式:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      ^ 匹配行开始,如:/^sed/匹配所有以sed开头的行。
      $ 匹配行结束,如:/sed$/匹配所有以sed结尾的行。
      . 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d。
      * 匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。
      [] 匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed。
      [^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
      \(..\) 匹配子串,保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
      & 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
      \< 匹配单词的开始,如:/\<love/匹配包含以love开头的单词的行。
      \> 匹配单词的结束,如/love\>/匹配包含以love结尾的单词的行。
      x\{m\} 重复字符x,m次,如:/0\{5\}/匹配包含5个0的行。
      x\{m,\} 重复字符x,至少m次,如:/0\{5,\}/匹配至少有5个0的行。
      x\{m,n\} 重复字符x,至少m次,不多于n次,如:/0\{5,10\}/匹配5~10个0的行。
    • 基本cmd如下:

      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
      a\ 在当前行下面插入文本。
      i\ 在当前行上面插入文本。
      c\ 把选定的行改为新的文本。
      d 删除,删除选择的行。
      D 删除模板块的第一行。
      s 替换指定字符
      h 拷贝模板块的内容到内存中的缓冲区。
      H 追加模板块的内容到内存中的缓冲区。
      g 获得内存缓冲区的内容,并替代当前模板块中的文本。
      G 获得内存缓冲区的内容,并追加到当前模板块文本的后面。
      l 列表不能打印字符的清单。
      n 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
      N 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
      p 打印模板块的行。
      P(大写) 打印模板块的第一行。
      q 退出Sed。
      b lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
      r file 从file中读行。
      t label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
      T label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
      w file 写并追加模板块到file末尾。
      W file 写并追加模板块的第一行到file末尾。
      ! 表示后面的命令对所有没有被选定的行发生作用。
      = 打印当前行号码。
      # 把注释扩展到下一个换行符以前。
      • g、G、h、H、x命令牵扯到Hold Space,详见sed 简明教程Hold Space章节

      • 注意,当在要替换的情况下(如上述s命令),可以使用如下标记:

        1
        2
        3
        4
        5
        6
        7
        g 表示行内全面替换。  
        p 表示打印行。
        w 表示把行写入一个文件。
        x 表示互换模板块中的文本和缓冲区中的文本。
        y 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
        \1 子串匹配标记
        & 已匹配字符串标记

command对应的伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool bexec = false
foreach line in file {
if ( match(address1) ){
bexec = true;
}

if ( bexec == true) {
EXEC(sed_cmd);
}

if ( match (address2) ) {
bexec = false;
}
}

例子

原始文本:

1
2
3
4
5
6
7
8
9
$ cat pets.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam

sed命令用法:

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
26
27
28
29
30
31
32
33
34
35
36
# 对3行到第6行,执行命令/This/d
$ sed '3,6 {/This/d}' pets.txt
This is my cat
my cat's name is betty
my dog's name is frank
my fish's name is george
This is my goat
my goat's name is adam

# 对3行到第6行,匹配/This/成功后,再匹配/fish/,成功后执行d命令
$ sed '3,6 {/This/{/fish/d}}' pets.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
my fish's name is george
This is my goat
my goat's name is adam

# 从第一行到最后一行,如果匹配到This,则删除之;如果前面有空格,则去除空格(注意是多cmd情况)
$ sed '1,${/This/d;s/^ *//g}' pets.txt
my cat's name is betty
my dog's name is frank
my fish's name is george
my goat's name is adam

# 使用&当做被匹配的变量,在其左右加点东西
$ sed 's/my/[&]/g' my.txt
This is [my] cat
[my] cat's name is betty
This is [my] dog
[my] dog's name is frank
This is [my] fish
[my] fish's name is george
This is [my] goat
[my] goat's name is adam

grep

参考链接:grep官方手册grep命令Linux grep 命令

grep是“global search regular expression and print out the line”的简称,意思是全面搜索正则表达式,并将其打印出来。

grep命令的选项用于对搜索过程的补充,而其命令的模式十分灵活,可以是变量、字符串、正则表达式。

注意:当模式中包含了空格,务必要用双引号将其引起来。

linux系统支持三种形式的grep命令:

  • grep:即标准grep
  • egrep:简称扩展grep命令,与grep -E等价,支持基本和扩展的正则表达式
  • fgrep:简称快速grep命令,与grep -F等价,不支持正则表达式,按照字符串表面意思进行匹配

命令格式

1
grep [-abcEFGhHilLnqrsvVwxy][-A<显示行数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][--help][范本样式][文件或目录...]
  • -r 或 --recursive:以递归的方式查找符合条件的文件,并打印出符合条件的行
  • -v 或 --invert-match:反向查找,打印出不符合条件行的内容
  • -i 或 --ignore-case : 忽略字符大小写的差别
  • -n 或 --line-number : 标出匹配行的行号
  • -c 或 --count : 计算匹配的个数

常见形式

1
2
3
4
5
6
# 在当前目录中,查找后缀为 file 的文件中包含 test 的文件,并打印出符合条件的行
grep test *file
# 以递归的方式查找符合条件的文件,并打印出符合条件的行
grep -r update /etc/acpi
# 从根目录开始查找所有扩展名为 .log 的文本文件,并找出包含 "ERROR" 的行:
find / -type f -name "*.log" | xargs grep "ERROR"

其他

补丁

diff

patch

ssh

远程登录命令,基本命令如下:

  • -l:指定用户名,或者用@表示,如果没有默认当前登录用户名
  • -p:指定端口号
  • -C:ssh传输数据时会进行数据压缩
  • -q:安静模式
  • -T:禁止远程分配终端
  • -n:关闭标准输入
  • -N:不执行远程命令
  • -f:把 ssh 放到后台运行
  • -v:打开调试模式
  • -b:绑定发起ssh连接的ip地址(针对多网卡用户)
  • 直接跟命令:仅仅远程执行一条命令
  • -L:正向代理
  • -R:反向代理
  • -D:socks5代理

正向代理(本地端口转发)

在本地运行,在本地启动端口,把本地端口数据转发到远端

用法:

1
ssh -L 本地地址:本地端口:目的地址:目的端口 跳转机地址
  • 目的地址目的端口需要跳转机能够访问,此ip和端口可以在跳转机自己上(localhost)或其他机器上(跳转机能够访问)
  • 本地地址本地端口本机(即执行该命令的机器)上的
  • 主要用于本机访问跳板机能够访问的端口
  • 可以加上-CqTnN 参数

反向代理(远程端口转发)

在远端运行,让远端启动端口,把远端端口数据转发到本地(下面的目标机器)。

用法:

1
ssh -R 源地址:源端口:目的地址:目的端口 本地机器地址
  • 目的地址目的端口需要远端机器(即执行该命令的机器)能够访问,同样此ip和端口可以在远端机器自己上(localhost)或其他机器上(本机能够访问)
  • 源地址源端口本地机器上的ip和端口
  • 主要用于在内网的远端机器把自己可以访问的端口暴露给了外网本地机器
  • 可以加上-CqTnN 参数

注意:这里可能需要修改本地机器的ssh配置文件/etc/ssh/sshd_config,添加:

1
GatewayPorts yes

socks5代理

用法:

在 HostA 的本地 1080 端口启动一个 socks5 服务,通过本地 socks5 代理的数据会通过 ssh 链接先发送给 HostB,再从 HostB 转发送给远程主机:

1
HostA$ ssh -D localhost:1080  HostB

那么在 HostA 上面,浏览器配置 socks5 代理为 127.0.0.1:1080,看网页时就能把数据通过 HostB 代理出去,类似 ss/ssr 版本,只不过用 ssh 来实现。

xargs

参考链接:xargs 命令教程- 阮一峰的网络日志

systemd

参考链接:Systemd 入门教程:命令篇Systemd 入门教程:实战篇

Systemd 默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录/lib/systemd/system/,真正的配置文件存放在这个目录中。


systemctl enable命令用于在上面两个目录之间,建立符号链接关系。

1
2
3
$ sudo systemctl enable clamd@scan.service
# 等同于
$ sudo ln -s '/lib/systemd/system/clamd@scan.service' '/etc/systemd/system/multi-user.target.wants/clamd@scan.service'
  • 如果配置文件里面设置了开机启动,systemctl enable命令相当于激活开机启动。

与之对应的,systemctl disable命令用于在两个目录之间,撤销符号链接关系,相当于撤销开机启动。

1
$ sudo systemctl disable clamd@scan.service
  • 配置文件的后缀名,就是该 Unit 的种类,比如sshd.socket。如果省略,Systemd 默认后缀名为.service,所以sshd会被理解成sshd.service

这里给出一个常用的脚本样例(以sshd.service为例):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Unit]
Description=OpenSSH server daemon # 当前服务的简单描述
Documentation=man:sshd(8) man:sshd_config(5) # 文档位置
After=network.target sshd-keygen.service # 如果network.target或sshd-keygen.service需要启动,那么sshd.service应该在它们之后启动
Wants=sshd-keygen.service # "弱依赖"关系,即如果"sshd-keygen.service"启动失败或停止运行,不影响sshd.service继续执行。

[Service]
EnvironmentFile=/etc/sysconfig/sshd # 指定当前服务的环境参数文件
ExecStart=/usr/sbin/sshd -D $OPTIONS # 定义启动进程时执行的命令
ExecReload=/bin/kill -HUP $MAINPID # 重启服务时执行的命令
Type=simple # 启动类型
KillMode=process # 定义 Systemd 如何停止 sshd 服务
Restart=on-failure # 定义 sshd 退出后,Systemd 的重启方式
RestartSec=42s # 表示 Systemd 重启服务之前,需要等待的秒数

[Install]
WantedBy=multi-user.target # 该服务所在的 Target
  • 注意,在修改配置文件后需要重新载入配置文件并重启相关服务:

    1
    2
    3
    4
    # 重新加载配置文件
    $ sudo systemctl daemon-reload
    # 重启相关服务
    $ sudo systemctl restart xxxx

常用命令

状态

1
2
3
4
5
6
7
8
# 显示系统状态
$ systemctl status

# 显示单个 Unit 的状态
$ sysystemctl status bluetooth.service

# 显示远程主机的某个 Unit 的状态
$ systemctl -H root@rhel7.example.com status httpd.service

管理

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
26
27
28
29
30
31
32
33
34
35
# 使能一个服务
$ sudo systemctl enable apache.service

# 失能一个服务
$ sudo systemctl disable apache.service

# 立即启动一个服务
$ sudo systemctl start apache.service

# 立即停止一个服务
$ sudo systemctl stop apache.service

# 重启一个服务
$ sudo systemctl restart apache.service

# 杀死一个服务的所有子进程
$ sudo systemctl kill apache.service

# 重新加载一个服务的配置文件
$ sudo systemctl reload apache.service

# 重载所有修改过的配置文件
$ sudo systemctl daemon-reload

# 查看配置文件的内容
$ systemctl cat sshd.service

# 显示某个 Unit 的所有底层参数
$ systemctl show httpd.service

# 显示某个 Unit 的指定属性的值
$ systemctl show -p CPUShares httpd.service

# 设置某个 Unit 的指定属性
$ sudo systemctl set-property httpd.service CPUShares=500

开机自启demo

首先编写配置文件ipchange.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=Automatic notification service of IP change
After=network.target sshd.service

[Service]
ExecStart=/home/jz/anaconda3/bin/python /home/jz/Code/Python/IPChange/main.py
ExecReload=/bin/kill -HUP $MAINPID
Type=simple
KillMode=control-group
Restart=on-failure
RestartSec=10s
Environment=

[Install]
WantedBy=multi-user.target
# Alias=sshd.service

并放在目录/lib/systemd/system/下,之后通过以下命令设置开机自启:

1
sudo systemctl enable ipchange.service

之后启动服务即可:

1
2
3
4
5
6
# 启动服务
sudo systemctl start ipchange.service
# 查看一下服务状态
sudo systemctl status ipchange.service
# 停止服务
sudo systemctl stop ipchange.service

如果修改配置文件以后,则需要重新加载配置文件,然后重新启动相关服务:

1
2
3
4
# 重新加载配置文件
sudo systemctl daemon-reload
# 重启相关服务
sudo systemctl restart ipchange.service

如果程序崩溃可以通过如下命令来查看日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看所有日志(默认情况下 ,只保存本次启动的日志)
$ sudo journalctl
# 显示尾部指定行数的日志
$ sudo journalctl -n 20
# 实时滚动显示最新日志
$ sudo journalctl -f
# 查看指定服务的日志
$ sudo journalctl /usr/lib/systemd/systemd
# 查看指定进程的日志
$ sudo journalctl _PID=1
# 查看某个 Unit 的日志
$ sudo journalctl -u ipchange.service
$ sudo journalctl -u ipchange.service --since today
# 实时滚动显示某个 Unit 的最新日志
$ sudo journalctl -u ipchange.service -f

find