查看当前日历:cal

cal命令用于查看当前日历,-y显示整年日历:

1
2
3
4
5
6
7
8
python@ubuntu:~$ cal
十一月 2019
日 一 二 三 四 五 六
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

显示或设置时间:date

设置时间格式(需要管理员权限):

1
date [MMDDhhmm[[CC]YY][.ss]] +format

MM为月,DD为天,hh为小时,mm为分钟;CC为年前两位,YY为年的后两位,ss为秒。

如: date 010203042016.55。

显示时间格式(date ‘+%y,%m,%d,%H,%M,%S’):

format格式含义
%Y,%y
%m
%d
%H
%M
%S

查看网络状态:netstat

netstat命令用于显示网络状态。

利用netstat指令可让你得知整个Linux系统的网络情况。

语法:

1
netstat [-acCeFghilMnNoprstuvVwx][-A<网络类型>][--ip]

参数说明

  • -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
5
[root@rocky8:~]# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 829/sshd
tcp6 0 0 :::22 :::* LISTEN 829/sshd

查看进程信息:ps

进程是一个具有一定独立功能的程序,它是操作系统动态执行的基本单元。

ps命令选项:

  • ps a 显示现行终端机下的所有程序,包括其他用户的程序。

  • ps -A 显示所有程序。

  • ps c 列出程序时,显示每个程序真正的指令名称,而不包含路 径,参数或常驻服务的标示。

  • ps -e 此参数的效果和指定"A"参数相同。

  • ps e 列出程序时,显示每个程序所使用的环境变量。

  • ps f 用ASCII字符显示树状结构,表达程序间的相互关系。

  • ps -H 显示树状结构,表示程序间的相互关系。

  • ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。

  • ps s 采用程序信号的格式显示程序状况。

  • ps u 以用户为主的格式来显示程序状况。

  • ps x 显示所有程序,不以终端机来区分。

选项含义
-a显示终端上的所有进程,包括其他用户的进程
-u显示进程的详细状态
-x显示没有控制终端的进程
-w显示加宽,以便显示更多的信息
-r只显示正在运行的进程

常见用法:

  • ps -e 查看所有进程信息(瞬时的)

  • ps -u root -N 查看所有不是root运行的进程

  • ps ax 显示所有进程状态状态

  • ps -ef |grep xxx 显示含有xxx的进程

实例:

1
2
3
4
5
6
7
8
9
[root@rocky8:~]# ps -A
PID TTY TIME CMD
1 ? 00:00:01 systemd
2 ? 00:00:00 kthreadd
……省略部分结果
2207 ? 00:00:00 kworker/1:1-events
2208 ? 00:00:00 kworker/0:0-ata_sff
2215 ? 00:00:00 kworker/0:2-ata_sff
2217 pts/1 00:00:00 ps

显示指定用户信息:

1
2
3
4
5
6
7
8
9
# ps -u root //显示root进程用户信息
PID TTY TIME CMD
1 ? 00:00:02 init
2 ? 00:00:00 kthreadd
3 ? 00:00:00 migration/0
……省略部分结果
30487 ? 00:00:06 gnome-terminal
30488 ? 00:00:00 gnome-pty-helpe
30489 pts/0 00:00:00 bash

显示所有进程信息,连同命令行

1
2
3
4
5
6
7
8
9
10
11
12
13
# ps -ef //显示所有命令,连带命令行
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 10:22 ? 00:00:02 /sbin/init
root 2 0 0 10:22 ? 00:00:00 [kthreadd]
root 3 2 0 10:22 ? 00:00:00 [migration/0]
root 4 2 0 10:22 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 10:22 ? 00:00:00 [watchdog/0]
root 6 2 0 10:22 ? /usr/lib/NetworkManager
……省略部分结果
root 31302 2095 0 17:42 ? 00:00:00 sshd: root@pts/2
root 31374 31302 0 17:42 pts/2 00:00:00 -bash
root 31400 1 0 17:46 ? 00:00:00 /usr/bin/python /usr/sbin/aptd
root 31407 31374 0 17:48 pts/2 00:00:00 ps -ef

以树状图显示进程关系:pstree

显示进程的关系

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
[root@rocky8:~]# pstree
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─atd
├─auditd───{auditd}
├─crond
├─dbus-daemon───{dbus-daemon}
├─firewalld───{firewalld}
├─irqbalance───{irqbalance}
├─login───bash───su───bash───su───bash
├─lsmd
├─mcelog
├─polkitd───5*[{polkitd}]
├─smartd
├─sshd─┬─sshd───sshd───bash
│ └─sshd───sshd───bash───pstree
├─systemd───(sd-pam)
├─systemd-journal
├─systemd-logind
├─systemd-udevd
└─tuned───3*[{tuned}]

[root@rocky8:~]# pstree -p
systemd(1)─┬─NetworkManager(816)─┬─{NetworkManager}(821)
│ └─{NetworkManager}(823)
├─atd(835)
├─auditd(768)───{auditd}(769)
├─crond(841)
├─dbus-daemon(796)───{dbus-daemon}(802)
├─firewalld(797)───{firewalld}(1030)
├─irqbalance(792)───{irqbalance}(801)
├─login(838)───bash(2012)───su(2043)───bash(2044)───su(2072)───bash(2076)
├─lsmd(793)
├─mcelog(798)
├─polkitd(1035)─┬─{polkitd}(1051)
│ ├─{polkitd}(1052)
│ ├─{polkitd}(1058)
│ ├─{polkitd}(1059)
│ └─{polkitd}(1072)
├─smartd(790)
├─sshd(829)─┬─sshd(1577)───sshd(1592)───bash(1593)
│ └─sshd(1859)───sshd(1863)───bash(1864)───pstree(2220)
├─systemd(1582)───(sd-pam)(1586)
├─systemd-journal(633)
├─systemd-logind(794)
├─systemd-udevd(662)
└─tuned(827)─┬─{tuned}(1168)
├─{tuned}(1217)
└─{tuned}(1248)
[root@rocky8:~]# pstree -c
systemd─┬─NetworkManager─┬─{NetworkManager}
│ └─{NetworkManager}
├─atd
├─auditd───{auditd}
├─crond
├─dbus-daemon───{dbus-daemon}
├─firewalld───{firewalld}
├─irqbalance───{irqbalance}
├─login───bash───su───bash───su───bash
├─lsmd
├─mcelog
├─polkitd─┬─{polkitd}
│ ├─{polkitd}
│ ├─{polkitd}
│ ├─{polkitd}
│ └─{polkitd}
├─smartd
├─sshd─┬─sshd───sshd───bash
│ └─sshd───sshd───bash───pstree
├─systemd───(sd-pam)
├─systemd-journal
├─systemd-logind
├─systemd-udevd
└─tuned─┬─{tuned}
├─{tuned}
└─{tuned}

特别表明在运行的进程:

1
# pstree -apnh //显示进程间的关系

同时显示用户名称:

1
# pstree -u //显示用户名称

动态显示进程:top

top命令用来动态显示运行中的进程。top命令能够在运行后,在指定的时间间隔更新显示信息。-d参数可以指定显示信息更新的时间间隔。

在top命令执行后,可以按下按键得到对显示的结果进行排序:

按键含义
M根据内存使用量来排序
P根据CPU占有率来排序
T根据进程运行时间的长短来排序
U可以根据后面输入的用户名来筛选进程
K可以根据后面输入的PID来杀死进程。
q退出
h获得帮助
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@rocky8:~]# top
top - 15:40:09 up 4:53, 3 users, load average: 1.06, 0.72, 0.37
Tasks: 161 total, 2 running, 159 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.2 us, 0.2 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.2 hi, 0.0 si, 0.0 st
MiB Mem : 1746.4 total, 1230.0 free, 246.9 used, 269.5 buff/cache
MiB Swap: 2068.0 total, 2068.0 free, 0.0 used. 1340.5 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
827 root 20 0 618180 31188 15248 S 0.3 1.7 0:30.76 tuned
1 root 20 0 175088 13464 9064 S 0.0 0.8 0:01.40 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
5 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 slub_flushwq
..................

更高级的命令是htop,但需要安装:

htop动态进程

终止进程:kill

kill命令指定进程号的进程,需要配合 ps 使用。

使用格式:

1
kill [-signal] pid

信号值从0到15,其中9为绝对终止,可以处理一般信号无法终止的进程。

关机重启:reboot、shutdown、init

命令含义
reboot重新启动操作系统
shutdown –r now重新启动操作系统,shutdown会给别的用户提示
shutdown -h now立刻关机,其中now相当于时间为0的状态
shutdown -h 20:25系统在今天的20:25 会关机
shutdown -h +10系统再过十分钟后自动关机
init 0关机
init 6重启

查看或配置网卡信息:ifconfig

ifconfig显示所有网卡的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@rocky8:~]# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.191 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::20c:29ff:fee9:9fb3 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:e9:9f:b3 txqueuelen 1000 (Ethernet)
RX packets 34362 bytes 34209026 (32.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 17179 bytes 1644986 (1.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 48 bytes 4080 (3.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 48 bytes 4080 (3.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

修改ip:

1
2
3
4
5
6
7
8
9
10
[root@rocky8:~]# sudo ifconfig ens33 192.168.40.10
[root@rocky8:~]# ifconfig ens33
ens33 Link encap:以太网 硬件地址 00:0c:29:59:65:f2
inet 地址:192.168.40.10 广播:192.168.40.255 掩码:255.255.255.0
inet6 地址: fe80::432f:6c4a:f47d:5f6b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
接收数据包:422818 错误:0 丢弃:0 过载:0 帧数:0
发送数据包:208692 错误:0 丢弃:0 过载:0 载波:0
碰撞:0 发送队列长度:1000
接收字节:603745130 (603.7 MB) 发送字节:12822615 (12.8 MB)

测试远程主机连通性:ping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@rocky8:~]# ping baidu.com
PING baidu.com (39.156.66.10) 56(84) bytes of data.
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=1 ttl=128 time=25.4 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=2 ttl=128 time=25.1 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=3 ttl=128 time=33.5 ms
^C
--- baidu.com ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 15100ms
rtt min/avg/max/mdev = 24.992/26.546/33.483/2.870 ms
[root@rocky8:~]# ping baidu.com -c 3
PING baidu.com (39.156.66.10) 56(84) bytes of data.
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=1 ttl=128 time=26.4 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=2 ttl=128 time=25.1 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=3 ttl=128 time=29.8 ms

--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 11041ms
rtt min/avg/max/mdev = 25.122/27.080/29.754/1.966 ms

本文参考:

Linux目录

Linux目录

  • /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录。所有的东西都是从这里开始。当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录)开始,再进入到home目录。

  • /bin: /usr/bin: 可执行二进制文件的目录,如常用的命令ls、tar、mv、cat等。

  • /boot:放置linux系统启动时用到的一些文件,如Linux的内核文件:/boot/vmlinuz,系统引导管理器:/boot/grub。

  • /dev:存放linux系统下的设备文件,访问该目录下某个文件,相当于访问某个设备,常用的是挂载光驱 mount /dev/cdrom /mnt。

  • /etc:系统配置文件存放的目录,不建议在此目录下存放可执行文件,重要的配置文件有 /etc/inittab、/etc/fstab、/etc/init.d、/etc/X11、/etc/sysconfig、/etc/xinetd.d。

  • /home:系统默认的用户家目录,新增用户账号时,用户的家目录都存放在此目录下,表示当前用户的家目录,edu 表示用户 edu 的家目录。

  • /lib: /usr/lib: /usr/local/lib:系统使用的函数库的目录,程序在执行过程中,需要调用一些额外的参数时需要函数库的协助。

  • /lost+fount:系统异常产生错误时,会将一些遗失的片段放置于此目录下。

  • /mnt: /media:光盘默认挂载点,通常光盘挂载于 /mnt/cdrom 下,也不一定,可以选择任意位置进行挂载。

  • /opt:给主机额外安装软件所摆放的目录。

  • /proc:此目录的数据都在内存中,如系统核心,外部设备,网络状态,由于数据都存放于内存中,所以不占用磁盘空间,比较重要的目录有 /proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/* 等。

  • /root:系统管理员root的家目录。

  • /sbin: /usr/sbin: /usr/local/sbin:放置系统管理员使用的可执行命令,如fdisk、shutdown、mount 等。与 /bin 不同的是,这几个目录是给系统管理员 root使用的命令,一般用户只能"查看"而不能设置和使用。

  • /tmp:一般用户或正在执行的程序临时存放文件的目录,任何人都可以访问,重要数据不可放置在此目录下。

  • /srv:服务启动之后需要访问的数据目录,如 www 服务需要访问的网页数据存放在 /srv/www 内。

  • /usr:应用程序存放目录,/usr/bin 存放应用程序,/usr/share 存放共享数据,/usr/lib 存放不能直接运行的,却是许多程序运行所必需的一些函数库文件。/usr/local: 存放软件升级包。/usr/share/doc: 系统说明文件存放目录。/usr/share/man: 程序说明文件存放目录。

  • /var:放置系统执行过程中经常变化的文件,如随时更改的日志文件 /var/log,/var/log/message:所有的登录文件存放目录,/var/spool/mail:邮件存放的目录,/var/run:程序或服务启动后,其PID存放在该目录下。

位于/home/user,称之为用户工作目录或家目录,表示方式:

1
2
/home/user
~

从/目录开始描述的路径为绝对路径,如:

1
2
cd /home
ls /usr

从当前位置开始描述的路径为相对路径,如:

1
2
cd ../../
ls abc/def

每个目录下都有**.和…**

. 表示当前目录

… 表示上一级目录,即父目录

根目录下的.和…都表示当前目录

基础操作

输出重定向:>

可将本应显示在终端上的内容保存到指定文件中。

如:ls > test.txt ( test.txt 如果不存在,则创建,存在则覆盖其内容 )

注意: >输出重定向会覆盖原来的内容,>>输出重定向则会追加到文件的尾部。

管道:|

管道:一个命令的输出可以通过管道做为另一个命令的输入。

“ | ”的左右分为两端,从左端写入到右端。

1
2
3
4
5
6
7
8
9
10
11
12
python@ubuntu:/bin$ ll -h |more   
总用量 13M
drwxr-xr-x 2 root root 4.0K 8月 4 2016 ./
drwxr-xr-x 26 root root 4.0K 7月 30 2016 ../
-rwxr-xr-x 1 root root 1014K 6月 24 2016 bash*
-rwxr-xr-x 1 root root 31K 5月 20 2015 bunzip2*
-rwxr-xr-x 1 root root 1.9M 8月 19 2015 busybox*
-rwxr-xr-x 1 root root 31K 5月 20 2015 bzcat*
lrwxrwxrwx 1 root root 6 5月 16 2016 bzcmp -> bzdiff*
-rwxr-xr-x 1 root root 2.1K 5月 20 2015 bzdiff*
lrwxrwxrwx 1 root root 6 5月 16 2016 bzegrep -> bzgrep*
--更多--

清屏:clear

clear作用为清除终端上的显示(类似于DOS的cls清屏功能),快捷键:Ctrl + l ( “l” 为字母 )。

切换工作目录: cd

Linux所有的目录和文件名大小写敏感

cd后面可跟绝对路径,也可以跟相对路径。如果省略目录,则默认切换到当前用户的主目录。

命令含义
cd相当于cd ~
cd ~切换到当前用户的主目录(/home/用户目录)
cd .切换到当前目录
cd …切换到上级目录
cd -进入上次所在的目录

查看命令位置:which

1
2
3
4
python@ubuntu:~$ which ls
/bin/ls
python@ubuntu:~$ which sudo
/usr/bin/sudo

查看文件内容

Linux系统中使用以下命令来查看文件的内容:

  • cat 由第一行开始显示文件内容

  • tac 从最后一行开始显示

  • nl 显示的时候,顺道输出行号

  • more 一页一页的显示文件内容

  • less与more 类似,但可以往前翻页

  • head 只看头几行

  • tail 只看尾巴几行

基本显示:cat、tac

语法:

1
cat [-AbEnTv]

选项与参数:

  • -A :相当于 -vET 的整合选项,可列出一些特殊字符而不是空白而已;

  • -v :列出一些看不出来的特殊字符

  • -E :将结尾的断行字节 $ 显示出来;

  • -T :将 [tab] 按键以 ^I 显示出来;

  • -b :列出行号,空白行不标行号

  • -n :列出行号,连同空白行也会有行号

1
2
3
4
5
6
7
8
[root@rocky8:/]# cat -b /etc/issue
1 \S
2 Kernel \r on an \m

[root@rocky8:/]# cat -n /etc/issue
1 \S
2 Kernel \r on an \m
3

tac与cat命令刚好相反,文件内容从最后一行开始显示,可以看出 tac 是 cat 的倒着写!如:

1
2
3
4
[root@rocky8:/]# tac /etc/issue

Kernel \r on an \m
\S

显示行号:nl

语法:

1
nl [-bnw] 文件

选项与参数:

  • -b :指定行号指定的方式,主要有两种:
    -b a :表示不论是否为空行,也同样列出行号(类似 cat -n);
    -b t :如果有空行,空的那一行不要列出行号(默认值);

  • -n :列出行号表示的方法,主要有三种:
    -n ln :行号在荧幕的最左方显示;
    -n rn :行号在自己栏位的最右方显示,且不加 0 ;
    -n rz :行号在自己栏位的最右方显示,且加 0 ;

  • -w :行号栏位的占用的位数。

1
2
3
4
[root@rocky8:/]# nl /etc/issue
1 \S
2 Kernel \r on an \m

分屏显示:more、less

1
2
3
4
5
6
7
8
[root@rocky8:/]# more /etc/man_db.config 
#
# Generated automatically from man.conf.in by the
# configure script.
#
# man.conf from man-1.6d
....(中间省略)....
--More--(28%) <== 光标在这里等待命令

more运行时可以输入的命令有:

  • 空白键 (space):代表向下翻一页;

  • Enter :代表向下翻『一行』;

  • /字串 :代表在这个显示的内容当中,向下搜寻『字串』这个关键字;

  • :f :立刻显示出档名以及目前显示的行数;

  • q :代表立刻离开 more ,不再显示该文件内容。

  • b 或 [ctrl]-b :代表往回翻页,不过这动作只对文件有用,对管线无用。

1
2
3
4
5
6
7
8
[root@rocky8:/]# less /etc/man.config
#
# Generated automatically from man.conf.in by the
# configure script.
#
# man.conf from man-1.6d
....(中间省略)....
: <== 这里可以等待你输入命令!

less运行时可以输入的命令有:

  • 空白键 :向下翻动一页;

  • [pagedown]:向下翻动一页;

  • [pageup] :向上翻动一页;

  • /字串 :向下搜寻『字串』的功能;

  • ?字串 :向上搜寻『字串』的功能;

  • n :重复前一个搜寻 (与 / 或 ? 有关!)

  • N :反向的重复前一个搜寻 (与 / 或 ? 有关!)

  • q :离开 less 这个程序;

取首尾n行:head、tail

head取出文件前面几行

语法:

1
head [-n number] 文件 

选项与参数:

  • -n :后面接数字,代表显示几行的意思

1
[root@rocky8:~]# head /etc/man.config

默认的情况中,显示前面 10 行!若要显示前 20 行,就得要这样:

1
[root@rocky8:~]# head -n 20 /etc/man.config

tail取出文件后面几行

语法:

1
tail [-n number] 文件 

选项与参数:

  • -n :后面接数字,代表显示几行的意思

  • -f :表示持续侦测后面所接的档名,要等到按下[ctrl]-c才会结束tail的侦测

1
2
3
[root@rocky8:~]# tail /etc/man.config
# 默认的情况中,显示最后的十行!若要显示最后的 20 行,就得要这样:
[root@rocky8:~]# tail -n 20 /etc/man.config

显示当前路径:pwd

1
2
[root@rocky8:~]# pwd
/root

选项与参数:

  • -P :显示出确实的路径,而非使用连结 (link) 路径。

1
2
3
4
5
[root@rocky8:~]# cd /var/mail
[root@rocky8:mail]# pwd
/var/mail
[root@rocky8:mail]# pwd -P
/var/spool/mail

文件操作

创建目录:mkdir

mkdir可以创建一个新的目录。

注意:新建目录的名称不能与当前目录中已有的目录或文件同名,并且目录创建者必须对当前目录具有写权限。

语法:

1
mkdir [-mp] 目录名称

选项与参数:

  • -m :指定被创建目录的权限,而不是根据默认权限 (umask) 设定

  • -p :递归创建所需要的目录

实例:-p递归创建目录:

1
2
3
4
5
[root@rocky8:~]# cd /tmp
[root@rocky8:tmp]# mkdir test <==创建一名为 test 的新目录
[root@rocky8:tmp]# mkdir test1/test2/test3/test4
mkdir: cannot create directory ‘test1/test2/test3/test4’: No such file or directory <== 没办法直接创建此目录啊!
[root@rocky8:tmp]# mkdir -p test1/test2/test3/test4

mkdir创建的目录权限默认根据umask得到,而-m参数可以指定被创建目录的权限:

1
2
3
4
5
6
7
8
9
[root@rocky8:~]# mkdir t1
[root@rocky8:~]# ll
total 0
drwxr-xr-x. 2 root root 6 Feb 20 15:06 t1
[root@rocky8:~]# mkdir t2 -m 711
[root@rocky8:~]# ll
total 0
drwxr-xr-x. 2 root root 6 Feb 20 15:06 t1
drwx--x--x. 2 root root 6 Feb 20 15:06 t2

删除文件:rm

可通过rm删除文件或目录。使用rm命令要小心,因为文件删除后不能恢复。为了防止文件误删,可以在rm后使用-i参数以逐个确认要删除的文件。

常用参数及含义如下表所示:

参数含义
-i以进行交互式方式执行
-f强制删除,忽略不存在的文件,无需提示
-r递归地删除目录下的内容,删除文件夹时必须加此参数

####ln: 建立链接文件

软链接:ln -s 源文件 链接文件

硬链接:ln 源文件 链接文件

软链接类似于Windows下的快捷方式,如果软链接文件和源文件不在同一个目录,源文件要使用绝对路径,不能使用相对路径。

硬链接只能链接普通文件不能链接目录。 两个文件占用相同大小的硬盘空间,即使删除了源文件,链接文件还是存在,所以-s选项是更常见的形式。

rename:修改文件名

rename命令是在Linux和Unix系统中使用的一个命令,用于批量重命名文件或目录。支持正则表达式。基本语法:

1
rename [选项] 表达式 替换的字符 文件...

命令选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@rocky8:~]#rename -h

Usage:
rename [options] <expression> <replacement> <file>...

Rename files.

Options:
-v, --verbose explain what is being done
-s, --symlink act on the target of symlinks
-n, --no-act do not make any changes
-o, --no-overwrite don't overwrite existing files

-h, --help display this help
-V, --version display version

For more details see rename(1).

下面是rename命令的常用选项

1
2
3
4
-v, --verbose : 显示详细的操作信息 
-s, --symlink : 对符号链接目标进行操作
-h, --help : 显示帮助信息并退出
-V, --version : 显示版本信息并退出

实例1:

1
2
3
4
5
6
7
8
9
10
[root@rocky8:~]#rename -v file afile file0?
`file01' -> `afile01'
`file02' -> `afile02'
`file03' -> `afile03'
`file04' -> `afile04'
`file05' -> `afile05'
`file06' -> `afile06'
`file07' -> `afile07'
`file08' -> `afile08'
`file09' -> `afile09'

实例2:

1
2
3
[root@rocky8:~]#rename file afile *
[root@rocky8:~]#ls
aafile01 aafile09 afile017 afile025 afile033 afile041 afile049 afile057 afile065 afile073 afile081 afile089 afile097......

grep:文本搜索

Linux系统中grep命令是一种强大的文本搜索工具,grep允许对文本文件进行模式查找。如果找到匹配模式, grep打印包含模式的所有行。

grep一般格式为:

1
grep [-选项] '搜索内容串' 文件名

在grep命令中输入字符串参数时,最好引号或双引号括起来。例如:grep 'a' 1.txt

在当前目录中,查找前缀有test字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:

1
2
3
4
$ grep test test* #查找前缀有test的文件包含test字符串的文件  
testfile1:This a Linux testfile! #列出testfile1 文件中包含test字符的行
testfile_2:This is a linux testfile! #列出testfile_2 文件中包含test字符的行
testfile_2:Linux test #列出testfile_2 文件中包含test字符的行

以递归的方式查找符合条件的文件。例如,查找指定目录/etc/acpi 及其子目录(如果存在子目录的话)下所有文件中包含字符串"update"的文件,并打印出该字符串所在行的内容,使用的命令为:

1
2
3
4
5
6
7
$ grep -r update /etc/acpi #以递归的方式查找“etc/acpi”  
#下包含“update”的文件
/etc/acpi/ac.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of IO.)
Rather than
/etc/acpi/resume.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of
IO.) Rather than
/etc/acpi/events/thinkpad-cmos:action=/usr/sbin/thinkpad-keys--update

反向查找。前面各个例子是查找并打印出符合条件的行,通过"-v"参数可以打印出不符合条件行的内容。

查找文件名中包含 test 的文件中不包含test 的行,此时,使用的命令为:

1
2
3
4
5
6
7
8
9
$ grep -v test* #查找文件名中包含test 的文件中不包含test 的行  
testfile1:helLinux!
testfile1:Linis a free Unix-type operating system.
testfile1:Lin
testfile_1:HELLO LINUX!
testfile_1:LINUX IS A FREE UNIX-TYPE OPTERATING SYSTEM.
testfile_1:THIS IS A LINUX TESTFILE!
testfile_2:HELLO LINUX!
testfile_2:Linux is a free unix-type opterating system.

查找文件:find

常用用法:

命令含义
find ./ -name test.sh查找当前目录下所有名为test.sh的文件
find ./ -name ‘*.sh’查找当前目录下所有后缀为.sh的文件
find ./ -name “[A-Z]*”查找当前目录下所有以大写字母开头的文件
find /tmp -size 2M查找在/tmp 目录下等于2M的文件
find /tmp -size +2M查找在/tmp 目录下大于2M的文件
find /tmp -size -2M查找在/tmp 目录下小于2M的文件
find ./ -size +4k -size -5M查找当前目录下大于4k,小于5M的文件
find ./ -perm 0777查找当前目录下权限为 777 的文件或目录

Linux find命令用来在指定目录下查找文件。任何位于参数之前的字符串都将被视为欲查找的目录名。如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件。并且将查找到的子目录和文件全部进行显示。

语法:

1
find path -option [ -print ] [ -exec -ok command ] {} \;

常用参数说明 :

  • -perm xxxx:权限为 xxxx的文件或目录

  • -user: 按照文件属主来查找文件。

  • -size n : n单位,b:512位元组的区块,c:字元数,k:kilo bytes,w:二个位元组

  • -mount, -xdev : 只检查和指定目录在同一个文件系统下的文件,避免列出其它文件系统中的文件

  • -amin n : 在过去 n 分钟内被读取过

  • -anewer file : 比文件 file 更晚被读取过的文件

  • -atime n : 在过去n天内被读取过的文件

  • -cmin n : 在过去 n 分钟内被修改过

  • -cnewer file :比文件 file 更新的文件

  • -ctime n : 在过去n天内被修改过的文件

  • -empty : 空的文件

  • -gid n or -group name : gid 是 n 或是 group 名称是 name

  • -ipath p, -path p : 路径名称符合 p 的文件,ipath 会忽略大小写

  • -name name, -iname name : 文件名称符合 name 的文件。iname 会忽略大小写

  • -type 查找某一类型的文件:

    • b - 块设备文件
    • d - 目录
    • c - 字符设备文件
    • p - 管道文件
    • l - 符号链接文件
    • f - 普通文件
  • -exec 命令名{} \ (注意:“}”和“\”之间有空格)

find实例:

显示当前目录中大于20字节并以.c结尾的文件名

1
find . -name "*.c" -size +20c 

将目前目录其其下子目录中所有一般文件列出

1
find . -type f

将目前目录及其子目录下所有最近 20 天内更新过的文件列出

1
find . -ctime -20

查找/var/log目录中更改时间在7日以前的普通文件,并在删除之前询问它们:

1
find /var/log -type f -mtime +7 -ok rm {} \;

查找前目录中文件属主具有读、写权限,并且文件所属组的用户和其他用户具有读权限的文件:

1
find . -type f -perm 644 -exec ls -l {} \;

查找系统中所有文件长度为0的普通文件,并列出它们的完整路径:

1
find / -type f -size 0 -exec ls -l {} \;

从根目录查找类型为符号链接的文件,并将其删除:

1
find / -type l -exec rm -rf {} \

从当前目录查找用户tom的所有文件并显示在屏幕上

1
find . -user tom

在当前目录中查找所有文件以.doc结尾,且更改时间在3天以上的文件,找到后删除,并且给出删除提示

1
find . -name *.doc  -mtime +3 -ok rm {} \;

在当前目录下查找所有链接文件,并且以长格式显示文件的基本信息

1
find . -type l -exec ls -l {} \;

在当前目录下查找文件名有一个小写字母、一个大写字母、两个数字组成,且扩展名为.doc的文件

1
find . -name '[a-z][A-Z][0-9][0-9].doc'

拷贝文件:cp

cp命令的功能是将给出的文件或目录复制到另一个文件或目录中,相当于DOS下的copy命令。

常用选项说明:

选项含义
-a该选项通常在复制目录时使用,它保留链接、文件属性,并递归地复制目录,简单而言,保持文件原有属性。
-f已经存在的目标文件而不提示
-i交互式复制,在覆盖目标文件之前将给出提示要求用户确认
-r若给出的源文件是目录文件,则cp将递归复制该目录下的所有子目录和文件,目标文件必须为一个目录名。
-v显示拷贝进度
-l创建硬链接(hard link),而非复制文件本身
-s复制成为符号链接 (symbolic link),相当于批量创建快捷方式
-u若 destination 比 source 旧才升级 destination !

cp vim_configure/ code/ -ivr 把文件夹 vim_configure 拷贝到 code 目录里。

移动文件:mv

mv命令用来移动文件或目录,也可以给文件或目录重命名。

常用选项说明:

选项含义
-f禁止交互式操作,如有覆盖也不会给出提示
-i确认交互方式操作,如果mv操作将导致对已存在的目标文件的覆盖,系统会询问是否重写,要求用户回答以避免误覆盖文件
-v显示移动进度

mv可以修改文件名:

1
2
3
4
5
6
7
8
9
[root@rocky8:~]#ll
total 4
-rw-------. 1 root root 1256 Feb 18 21:18 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 Feb 19 11:43 test.txt
[root@rocky8:~]#mv test.txt test
[root@rocky8:~]#ll
total 4
-rw-------. 1 root root 1256 Feb 18 21:18 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 Feb 19 11:43 test

归档管理:tar

此命令可以把一系列文件归档到一个大文件中,也可以把档案文件解开以恢复数据。

tar使用格式 tar [参数] 打包文件名 文件

tar命令参数很特殊,其参数前面可以使用“-”,也可以不使用。

常用参数:

参数含义
-c生成档案文件,创建打包文件
-v列出归档解档的详细过程,显示进度
-f指定档案文件名称,f后面一定是.tar文件,所以必须放选项最后
-t列出档案中包含的文件
-x解开档案文件

注意:除了f需要放在参数的最后,其它参数的顺序任意。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@rocky8:~]# tar -cvf test.tar {1..3}.txt
1.txt
2.txt
3.txt
[root@rocky8:~]# ll
total 12
-rw-r--r--. 1 root root 0 Feb 20 15:14 1.txt
-rw-r--r--. 1 root root 0 Feb 20 15:14 2.txt
-rw-r--r--. 1 root root 0 Feb 20 15:14 3.txt
-rw-r--r--. 1 root root 10240 Feb 20 15:14 test.tar
[root@rocky8:~]# rm -rf *.txt
[root@rocky8:~]# ll
total 12
-rw-r--r--. 1 root root 10240 Feb 20 15:14 test.tar
[root@rocky8:~]# tar -xvf test.tar
1.txt
2.txt
3.txt
[root@rocky8:~]# ll
total 12
-rw-r--r--. 1 root root 0 Feb 20 15:14 1.txt
-rw-r--r--. 1 root root 0 Feb 20 15:14 2.txt
-rw-r--r--. 1 root root 0 Feb 20 15:14 3.txt
-rw-r--r--. 1 root root 10240 Feb 20 15:14 test.tar

文件压缩解压:gzip、bzip2

tar与gzip命令结合使用实现文件打包、压缩。 tar只负责打包文件,但不压缩,用gzip压缩tar打包后的文件,其扩展名一般用xxxx.tar.gz。

gzip使用格式如下:

1
gzip  [选项]  被压缩文件

常用选项:

选项含义
-d解压文件
-r压缩文件
1
2
3
4
5
6
7
8
[root@rocky8:~]# ll *.tar*
-rw-r--r--. 1 root root 10240 Feb 20 15:14 test.tar
[root@rocky8:~]# gzip -r test.tar test.tar.gz ==>或者:gzip test.tar
[root@rocky8:~]# ll *.tar*
-rw-r--r--. 1 root root 131 Feb 20 15:14 test.tar.gz
[root@rocky8:~]# gzip -d test.tar.gz
[root@rocky8:~]# ll *.tar*
-rw-r--r--. 1 root root 10240 Feb 20 15:14 test.tar

tar命令中-z选项可以调用gzip实现了一个压缩的功能,实行一个先打包后压缩的过程。

压缩用法:tar zcvf 压缩包包名 文件1 文件2 …

例如: tar zcvf test.tar.gz 1.c 2.c 3.c 4.c把 1.c 2.c 3.c 4.c 压缩成 test.tar.gz

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky8:~]# ls
1.c 2.c 3.c 4.c
[root@rocky8:~]# tar -zcvf test.tar.gz {1..4}.c
1.c
2.c
3.c
4.c
[root@rocky8:~]# ls
1.c 2.c 3.c 4.c test.tar.gz
[root@rocky8:~]# gzip -d test.tar.gz
[root@rocky8:~]# ls
1.c 2.c 3.c 4.c test.tar

解压用法: tar zxvf 压缩包包名

例如:

1
2
3
4
5
6
7
8
9
[root@rocky8:~]# ls
new.tar.gz test.tar test.tar.gz
[root@rocky8:~]# tar -zxvf new.tar.gz
1.c
2.c
3.c
4.c
[root@rocky8:~]# ls
1.c 2.c 3.c 4.c new.tar.gz test.tar test.tar.gz

解压到指定目录:-C (解压时可以不指定-z选项)

1
2
3
4
5
6
7
8
9
[root@rocky8:~]# ls
1.c 2.c 3.c 4.c new.tar.gz test.tar test.tar.gz
[root@rocky8:~]# tar -zxvf new.tar.gz -C number/
1.c
2.c
3.c
4.c
[root@rocky8:~]# ls number/
1.c 2.c 3.c 4.c

bzip2命令跟gzip用法类似

压缩用法:tar jcvf 压缩包包名 文件…(tar jcvf bk.tar.bz2 *.c)

解压用法:tar jxvf 压缩包包名 (tar jxvf bk.tar.bz2)

文件压缩解压:zip、unzip

通过zip压缩文件的目标文件不需要指定扩展名,默认扩展名为zip。

压缩文件:zip [-r] 目标文件(没有扩展名) 源文件

解压文件:unzip -d 解压后目录文件 压缩文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@rocky8:~]# ls
1.txt 2.txt 3.txt 4.txt test.tar
[root@rocky8:~]# zip myzip *.txt
adding: 1.txt (stored 0%)
adding: 2.txt (stored 0%)
adding: 3.txt (stored 0%)
adding: 4.txt (stored 0%)
[root@rocky8:~]# ls
1.txt 2.txt 3.txt 4.txt myzip.zip test.tar
[root@rocky8:~]# rm -f *.txt *.tar
[root@rocky8:~]# ls
myzip.zip
[root@rocky8:~]# unzip myzip
Archive: myzip.zip
extracting: 1.txt
extracting: 2.txt
extracting: 3.txt
extracting: 4.txt
[root@rocky8:~]# ls
1.txt 2.txt 3.txt 4.txt myzip.zip

本文参考:

vim的使用

什么是 vim?

Vim是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。vim 的官方网站 (http://www.vim.org)

vim 键盘图:

img

基本上vi可以分为三种状态:

  • 命令模式(command mode)

  • 插入模式(Insert mode)

  • 底行模式(last line mode)

vi/vim的三种模式

vi/vim主要分为三种模式,分别是命令模式(Command mode)输入模式(Insert mode)**和**底线命令模式(Last line mode)

img

这三种模式的作用分别是:

输入模式

在命令模式下输入插入命令i、附加命令a 、打开命令o、修改命令c、取代命令r或替换命令s都可以进入文本输入模式。在该模式下,用户输入的任何字符都被Vi当做文件内容保存起来,并将其显示在屏幕上。在文本输入过程中,若想回到命令模式下,按键ESC即可。

命令模式

用户刚刚启动 vi/vim,便进入了命令模式。 任何时候,不管用户处于何种模式,只要按一下ESC键,即可使Vi进入命令模式;

此状态下敲击键盘动作会被Vim识别为命令,输入: 可切换到底线命令模式,以在最底一行输入命令。

若想要编辑文本:启动Vim,进入了命令模式,按下i,切换到输入模式。

底行模式

在命令模式下按下:(英文冒号)就进入了底行命令模式。

底线命令模式可以输入单个或多个字符的命令,可用的命令非常多。

在底线命令模式中,基本的命令有(已经省略了冒号):

  • q 退出程序

  • w 保存文件

按ESC键可随时退出底线命令模式。

vim基础操作

进入输入模式(Insert mode)

1574384484673

  • i: 插入光标前一个字符

  • I: 插入行首

  • a: 插入光标后一个字符

  • A: 插入行未

  • o: 向下新开一行,插入行首

  • O: 向上新开一行,插入行首

在进入输入模式后, vi 画面的左下角处会出现『–INSERT–』的字样

进入替换模式(Replace mode)

  • r : 只会取代光标所在的那一个字符一次

  • R: 会一直取代光标所在的文字,直到按下ESC为止

在进入输入模式后, vi 画面的左下角处会出现『–REPLACE–』的字样

命令模式常用命令

移动光标
移动光标的方法
h 或 向左箭头键(←)光标向左移动一个字符
j 或 向下箭头键(↓)光标向下移动一个字符
k 或 向上箭头键(↑)光标向上移动一个字符
l 或 向右箭头键(→)光标向右移动一个字符
向下移动 30 行,可以使用 “30j” 或 “30↓” 的组合按键
[Ctrl] + [f]屏幕『向下』移动一页,相当于 [Page Down]按键 (常用)
[Ctrl] + [b]屏幕『向上』移动一页,相当于 [Page Up] 按键 (常用)
[Ctrl] + [d]屏幕『向下』移动半页
[Ctrl] + [u]屏幕『向上』移动半页
+光标移动到非空格符的下一行
-光标移动到非空格符的上一行
n表示空格光标向右移动这一行的 n 个字符。例如 20 则光标会向后面移动 20 个字符距离。
0 或功能键[Home]这是数字『 0 』:移动到这一行的最前面字符处 (常用)
$ 或功能键[End]移动到这一行的最后面字符处(常用)
H光标移动到这个屏幕的最上方那一行的第一个字符
M光标移动到这个屏幕的中央那一行的第一个字符
L光标移动到这个屏幕的最下方那一行的第一个字符
G移动到这个文档的最后一行(常用)
nGn 为数字。移动到这个文件的第 n 行。例如 20G 则会移动到这个文件的第 20 行(可配合 :set nu)
gg移动到这个文档的第一行,相当于 1G
nn 为数字。光标向下移动 n 行(常用)
删除操作
删除操作删除后会添加到剪切板,相当于剪切
x, Xx为向后删除一个字符 (相当于 [del] 按键), X为向前删除一个字符(相当于 [backspace] )
nxn 为数字,连续向后删除 n 个字符。例如10x表示连续删除 10 个字符。
dd删除光标所在的一整行(常用)
nddn 为数字。删除光标所在的向下 n 行,例如 20dd 则是删除 20 行
d1G删除光标所在行到首行的所有数据
dG删除光标所在行到最后一行的所有数据
d$删除光标所在位置到该行的最后一个字符
d0删除光标所在位置到该行的最前面一个字符
撤销&复原&重复
撤销&复原
u撤销操作,相对于普通编辑器里面的ctrl+z
Ctrl+r恢复操作,相对于普通编辑器里面的ctrl+y
.就是小数点!可重复前一个动作
复制&粘贴
复制&粘贴
yy复制光标所在行
nyyn 为数字。复制光标所在的向下 n 行,例如 20yy 则是复制 20 行
y1G复制光标所在行到第一行的所有数据
yG复制光标所在行到最后一行的所有数据
y0复制光标所在的那个字符到该行行首的所有数据
y$复制光标所在的那个字符到该行行尾的所有数据
p, Pp 为将已复制的数据在光标下一行贴上,P 则为贴在光标上一行!
合成行
  • J: 将光标所在行与下一行的数据结合成同一行

搜索
搜索
/word向光标之下寻找一个名称为 word 的字符串。
?word向光标之上寻找一个字符串名称为 word 的字符串。
n代表重复前一个搜寻的动作,根据前面输入的/word还是?word向下或向上搜索下一个匹配的字符串。
N表示反向搜索,与n的搜索方向相反。
替换
替换
:n1,n2s/word1/word2/g在第 n1 与 n2 行之间寻找word1并替换为word2!比如『:100,200s/vbird/VBIRD/g』表示在100到200行之间将vbird替换为VBIRD
:1,$s/word1/word2/g:%s/word1/word2/g$表示最后一行,%s表示所有行。
:1,$s/word1/word2/gc:%s/word1/word2/gcgc中的c表示取代前显示提示字符给用户确认 (confirm) !
底行命令模式的常用操作
底行命令模式
:w保存编辑数据
:w!若文件属性为『只读』时,强制写入该文件。不过,到底能不能写入, 还是跟你对该文件的文件权限有关啊!
:q离开 vi
:q!若曾修改过文件,又不想储存,使用 ! 为强制离开不储存文件。
惊叹号 (!) 在 vi 当中,常常具有『强制』的意思~
:wq储存后离开,若为 :wq! 则为强制储存后离开
ZZ若文件没有更动,则不储存离开,若文件已经被更动过,则储存后离开!
:w [filename]另存为
:r [filename]将另一个文件『filename』的数据加到光标所在行后面
:n1,n2 w [filename]将 n1 到 n2 行的内容储存成 filename 这个文件。
:! command暂时离开 vi 到指令行模式下执行 command 的显示结果!例如 『:! ls /home』即可在 vi 当中察看 /home 底下以 ls 输出的文件信息!
:set nu会在每一行的前缀显示该行的行号
:set nonu取消行号显示

示例:

1
2
将当前路径插入到光标的下一行
:r!pwd

可视模式

v 进入字符可视化模式: 文本选择是以字符为单位的。
V 进入行可视化模式: 文本选择是以行为单位的。
Ctrl+v 进入块可视化模式 : 选择一个矩形内的文本。

可视模式下可进行如下操作:

可视模式操作
A在选定的部分后面插入内容
I在选定的部分前面插入内容
d删除选定的部分
c删除选定的部分并进入插入模式(有批量替换效果)
r把选定的部分全部替换为指定的单个字符
>>向右缩进一个单位,更适合行可视化模式
<<向左缩进一个单位,更适合行可视化模式
gu选中区域转为小写
gU选中区域转为大写
g~大小写互调

可视模式下,选中的区域是由两个端点来界定的(一个在左上角,一个在右下角),在默认情况下只可以控制右下角的端点,而使用o按键则可以在左上角和右下角之间切换控制端点。

VIM快速复习

按:冒号即可进入last line mode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:set nu 列出行号
:set nonu 取消行号
:#7 跳到文件中的第7行
/keyword 查找字符 按n向下
?keyword 查找字符 按N向下
:n1,n2/word1/word2/gc 替换指定范围单词,c表示提示
:w 保存文件
:w filename 以指定的文件名另存
:n1,n2 w [filename] 将 n1 到 n2行另存
:r [filename] 读入另一个文件加到光标所在行后面
:! ls /home 在vi当中察看ls输出信息!
:q离开vi
:wq:ZZ:x 保存并退出vi
!强制执行
:% s/^/#/g 来在全部内容的行首添加 # 号注释
:1,10 s/^/#/g1~10 行首添加 # 号注释

从command mode进入Insert mode

按i在当前位置编辑按a在当前位置的下一个字符编辑按o插入新行,从行首开始编辑按R(Replace mode):R会一直取代光标所在的文字,直到按下 ESC为止;(常用)

按ESC键退回command mode

h←j↓k↑l→前面加数字移动指定的行数或字符数
1、翻页bu上下整页,ud上下半页

1
2
3
4
ctrl+b:上移一页。
ctrl+f:下移一页。
ctrl+u:上移半页。
ctrl+d:下移半页。

2、行定位

1
2
3
4
5
7gg7G:定位第7行首字符。(可能只在Vim中有效)
G:移动到文章的最后。
7H:当前屏幕的第7行行首
M:当前屏幕中间行的行首
7L:当前屏幕的倒数第7行行首

3、当前行定位

1
2
3
4
5
$:移动到光标所在行的“行尾”。
0或^:移动到光标所在行的“行首”
w:光标跳到下个单词的开头
e:光标跳到下个单词的字尾
b:光标回到上个单词的开头

4、编辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
x:剪切当前字符
7x:剪切从当前位置起7个字符
大写的X,表示从前面一个字符开始往前计算
dd:剪切光标所在行。
7dd:从光标所在行开始剪切7行
d7G 删除光标所在到第7行的所有数据
yw:复制当前单词
7yw:复制从当前位置起7个单词
yy:复制当前行
6yy:从当前行起向下复制6行
y7G 复制游标所在列到第7列的所有数据
p:粘贴
u:撤销
ctrl+r:取消撤销
cw:删除当前单词(从光标位置开始计算),并进入插入模式
c7w:删除7个单词并进入插入模式

多行编辑,vim支持,vi不支持

按ctrl+V进入块模式,上下键选中快,按大写G选择到末尾,上下左右键移动选择位置按大写I进去编辑模式,输入要插入的字符,编辑完成按ESC退出选中要替换的字符后,按c键全部会删除,然后输入要插入的字符,编辑完成按ESC退出选中要替删除的字符后,按delete键,则会全部删除

按shift+V可进入行模式,对指定行操作

vim练习

1、创建目录/tmp/test,将/etc/man.config复制到该目录下

1
2
3
# mkdir -p /tmp/test
# cp /etc/man.config /tmp/test/
# cd /tmp/test/

2、用vim编辑man.config文件:

1
vim man.config

3、设置显示行号; 移动到第58行,向右移动40个字符,查看双引号内的是什么目录;

1
2
3
set nu
58G 或58gg
40-> 或40空格 目录为:/dir/bin/foo

4、移动到第一行,并向下查找“bzip2”这个字符串,它在第几行;

1
2
3
移动到最后一行,并向上查找该字符串;
gg 或1G
/bzip 137行 ?bzip2

5、将50行到100行之间的man更改为MAN,并且 逐个挑选 是否需要修改;

1
2
若在挑选过程中一直按y,结果会在最后一行出现改变了几个man?
:50,100s/man/MAN/gc 25次替换

6、修改完后,突然反悔了,要全部复原,有哪些方法?

1
2
3
一直按u键	
或者
:q!强制不保存退出后,再重新打开该文件

7、复制65到73这9行的内容(含有MANPATH_MAP),并且粘贴到最后一行之后;

1
65gg65G到该行后,9yy,G 移动到最后一行,p粘贴

8、21行到42行之间开头为#符号的批注数据不要了,如何删除;

1
21G到该行 22dd

9、将这个文件另存为man.test.config的文件

1
:w man.test.config

10、到第27行,并且删除15个字符,结果出现的第一个字符是什么?

1
27gg15x

11、在第一行新增一行,在该行内输入“I am a student ”

1
gg到第一行 O输入即可 说明:o是在当前行之后插入一行,O是在当前行之前插入一行

12、保存并退出

1
:wq

正则表达式(待写)

Linux管道命令

Linux的管道命令是’|’,通过它可以对数据进行连续处理,其示意图如下:

img

注意:

1)管道命令仅处理标准输出,对于标准错误输出,将忽略

2)管道命令右边命令,必须能够接收标准输入流命令才行,否则传递过程中数据会抛弃。

常用来作为接收数据管道命令有: less,more,head,tail,而ls, cp, mv就不行。

wc - 统计字数

可以计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据。

1
2
3
4
5
6
7
8
9
10
11
wc [-lwm] [filename]
-l: 统计行数
-w:统计英文单词
-m:统计字符数
python@xxx:~$ wc -l /etc/passwd
49 /etc/passwd
python@xxx:~$ wc -w /etc/passwd
81 /etc/passwd
python@xxx:~$ wc -m /etc/passwd
2696 /etc/passwd
12345678910

在默认的情况下,wc将计算指定文件的行数、字数,以及字节数。使用的命令为:

1
2
3
$ wc testfile           # testfile文件的统计信息  
3 92 598 testfile # testfile文件的行数为3、单词数92、字节数598
12

其中,3 个数字分别表示testfile文件的行数、单词数,以及该文件的字节数。

如果想同时统计多个文件的信息,例如同时统计testfile、testfile_1、testfile_2,可使用如下命令:

1
2
3
4
5
6
$ wc testfile testfile_1 testfile_2  #统计三个文件的信息  
3 92 598 testfile #第一个文件行数为3、单词数92、字节数598
9 18 78 testfile_1 #第二个文件的行数为9、单词数18、字节数78
3 6 32 testfile_2 #第三个文件的行数为3、单词数6、字节数32
15 116 708 总用量 #三个文件总共的行数为15、单词数116、字节数708
12345

cut - 列选取命令

1
2
3
4
5
选项与参数:
-d :后面接分隔字符。与 -f 一起使用;
-f :依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思;
-c :以字符 (characters) 的单位取出固定字符区间;
1234

cut以行为单位,根据分隔符把行分成若干列,这样就可以指定选取哪些列了。

1
2
3
4
5
6
7
cut -d '分隔字符' -f 选取的列数
echo $PATH|cut -d ':' -f 2 --选取第2列
echo $PATH|cut -d ':' -f 3,5 --选取第3列和第5列
echo $PATH|cut -d ':' -f 3-5 --选取第3列到第5列
echo $PATH|cut -d ':' -f 3- --选取第3列到最后1列
echo $PATH|cut -d ':' -f 1-3,5 --选取第1到第3列还有第5列
123456

只显示/etc/passwd的用户和shell:

1
2
3
4
5
#cat /etc/passwd | cut -d ':' -f 1,7 
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh
1234

grep - 行选取命令

grep一般格式为:

1
2
grep [-cinv] '查找的字符串' filename
1

在grep命令中输入字符串参数时,最好引号或双引号括起来。例如:grep 'a' 1.txt

常用选项说明:

选项含义
-v显示不包含匹配文本的所有行(相当于求反)
-n显示匹配行及行号
-i忽略大小写
-c计算找到的行数

grep搜索内容串可以是正则表达式,常用正则表达式:

参数含义
^a行首,搜寻以 m 开头的行;grep -n ‘^a’ 1.txt
ke$行尾,搜寻以 ke 结束的行;grep -n ‘ke$’ 1.txt
[Ss]igna[Ll]匹配 [] 里中一系列字符中的一个;搜寻匹配单词signal、signaL、Signal、SignaL的行;grep -n ‘[Ss]igna[Ll]’ 1.txt
..匹配一个非换行符的字符;grep -n ‘e.e’ 1.txt可以匹配 eee,eae,eve,但是不匹配 ee,eaae;
*匹配零个或多个先前字符
[^]匹配一个不在指定范围内的字符
\(..\)标记匹配字符
\锚定单词的开始
\<锚定单词的开头
\>锚定单词的结束
x\{m\}重复字符x,m次
x\{m,\}重复字符x,至少m次
x\{m,n\}重复字符x,至少m次,不多于n次
\w匹配文字和数字字符,也就是[A-Za-z0-9]
\b单词锁定符

实例:显示所有以“h”结尾的行
grep h$
匹配所有以“a”开头且以“e”结尾的,中间包含2个字符的单词
grep ‘<a…e>’
显示所有包含一个”y”或”h”字符的行
grep [yh]
显示不包含字母a~k 且后紧跟“pple”的单词

1
grep [^a-k]pple

从系统词典中选择所有以“c”开头且以“o”结尾的单词grep '\<c.*o\>'
找出一个文件中或者输出中找到包含*的行grep '\*'
显示所有包含每个字符串至少有20个连续字母的单词的行
grep [a-Z]\{20,\}

sort - 排序

语法:

1
2
sort [-fbMnrtuk] [file or stdin]
1

参数说明

  • -f :忽略大小写的差异,例如 A 与 a 视为编码相同;

  • -b :忽略最前面的空格符部分;

  • -M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;

  • -n :使用『纯数字』进行排序(默认是以文字型态来排序的);

  • -r :反向排序;

  • -u :就是 uniq ,相同的数据中,仅出现一行代表;

  • -t :分隔符,默认是用 [tab] 键来分隔;

  • -k :以哪个区间 (field) 来进行排序

默认是以第一个字符升序排序:

1
2
3
4
5
6
7
# cat /etc/passwd | sort 
adm:x:3:4:adm:/var/adm:/sbin/nologin
avahi-autoipd:x:100:156:avahi-autoipd:/var/lib/avahi-autoipd:/sbin/nologin
avahi:x:70:70:Avahi daemon:/:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
......
123456

以第3列排序:

1
2
3
4
5
6
7
[root@www ~]# cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
123456

使用数字排序:

1
2
3
4
5
cat /etc/passwd | sort -t ':' -k 3n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
1234

倒序排序:

1
2
3
4
5
6
7
8
cat /etc/passwd | sort -t ':' -k 3nr
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
ntp:x:106:113::/home/ntp:/bin/false
messagebus:x:105:109::/var/run/dbus:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
或者
cat /etc/passwd | sort -t ':' -k 3 -nr
1234567

先以第六个域的第2个字符到第4个字符进行正向排序,再基于第一个域进行反向排序:

1
2
3
4
5
6
cat /etc/passwd |  sort -t ':' -k 6.2,6.4 -k 1r      
sync:x:4:65534:sync:/bin:/bin/sync
proxy:x:13:13:proxy:/bin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
12345

查看/etc/passwd有多少个shell:

方法对/etc/passwd的第七个域排序并去重,然后统计行数:

1
2
3
4
5
6
7
8
9
10
[root@VM_0_9_centos ~]# cat /etc/passwd |  sort -t':' -k 7 -u
root:x:0:0:root:/root:/bin/bash
syslog:x:996:994::/home/syslog:/bin/false
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
bin:x:1:1:bin:/bin:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@VM_0_9_centos ~]# cat /etc/passwd | sort -t':' -k 7 -u|wc -l
6
123456789

uniq - 去重

1
2
3
4
5
选项与参数:
-i :忽略大小写字符的不同;
-c :进行计数
-u :只显示唯一的行
1234

该命令用于排完序之后,对排序结果进行去重

1
2
3
4
5
6
7
8
9
10
11
12
13
python@xxx:~$ last | cut -d ' ' -f 1  | sort | uniq

haha
python
reboot
wtmp
python@xxx:~$ last | cut -d ' ' -f 1 | sort | uniq -c
1
2 haha
22 python
7 reboot
1 wtmp
123456789101112

排序文件,默认是去重:

1
2
3
4
5
#cat words | sort |uniq
friend
hello
world
1234

排序之后删除了重复行,同时在行首位置输出该行重复的次数:

1
2
3
4
5
#sort testfile | uniq -c
1 friend
3 hello
2 world
1234

仅显示存在重复的行,并在行首显示该行重复的次数:

1
2
3
4
#sort testfile | uniq -dc
3 hello
2 world
123

仅显示不重复的行:

1
2
3
sort testfile | uniq -u
friend
12

tee - 同时输出多个文件

从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。

一般情况下用重定向实现,需要同时输出多个文件时可以使用该命令。

参数

  • -a或–append  附加到既有文件的后面,而非覆盖它.

将输出同时保存到多个文件中,同时将输出内容显示到控制台:

1
2
3
4
5
6
7
8
9
10
python@xxx:~/test$ echo "hello world"|tee f1 f2 
hello world
python@xxx:~/test$ cat f1
hello world
python@xxx:~/test$ echo "hello world"|tee f1 f2 -a
hello world
python@xxx:~/test$ cat f1
hello world
hello world
123456789

tr - 替换指定的字符

不指定参数时,即表示替换指定的字符为另一个字符,支持指定的字符集合。

参数说明:

  • -d, --delete:删除指定的字符

  • -s, --squeeze-repeats:缩减连续重复的字符成指定的单个字符

字符集合的范围:

  • \NNN 八进制值的字符 NNN (1 to 3 为八进制值的字符)

  • \ 反斜杠

  • \a Ctrl-G 铃声

  • \b Ctrl-H 退格符

  • \f Ctrl-L 走行换页

  • \n Ctrl-J 新行

  • \r Ctrl-M 回车

  • \t Ctrl-I tab键

  • \v Ctrl-X 水平制表符

  • CHAR1-CHAR2 :字符范围从 CHAR1 到 CHAR2 的指定,范围的指定以 ASCII 码的次序为基础,只能由小到大,不能由大到小。

  • [CHAR*] :这是 SET2 专用的设定,功能是重复指定的字符到与 SET1 相同长度为止

  • [CHAR*REPEAT] :这也是 SET2 专用的设定,功能是重复指定的字符到设定的 REPEAT 次数为止(REPEAT 的数字采 8 进位制计算,以 0 为开始)

  • [:alnum:] :所有字母字符与数字

  • [:alpha:] :所有字母字符

  • [:blank:] :所有水平空格

  • [:cntrl:] :所有控制字符

  • [:digit:] :所有数字

  • [:graph:] :所有可打印的字符(不包含空格符)

  • [:lower:] :所有小写字母

  • [:print:] :所有可打印的字符(包含空格符)

  • [:punct:] :所有标点字符

  • [:space:] :所有水平与垂直空格符

  • [:upper:] :所有大写字母

  • [:xdigit:] :所有 16 进位制的数字

  • [=CHAR=] :所有符合指定的字符(等号里的 CHAR,代表你可自订的字符)

将文件testfile中的小写字母全部转换成大写字母:

1
2
3
4
cat testfile |tr a-z A-Z 

cat testfile |tr [:lower:] [:upper:]
123

缩减连续重复的字符成指定的单个字符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
python@xxx:~/test$ cat t
dddddddsssssdd
eeeeeeeeee
aaaaaaaaaaaaaa
vvvvvvvvvvvvvv
python@xxx:~/test$ cat t|tr -s 'se'
dddddddsdd
e
aaaaaaaaaaaaaa
vvvvvvvvvvvvvv
python@xxx:~/test$ cat t|tr -s 'sdeav'
dsd
e
a
v
123456789101112131415

删除指定的字符:

1
2
3
4
5
python@xxx:~/test$ cat t|tr -d 'dv'
sssss
eeeeeeeeee
aaaaaaaaaaaaaa
1234

join - 文件按行连接

将两个文件中指定栏位相同的行连接起来。即按照两个文件中共同拥有的某一列,将对应的行拼接成一行。

注意:在使用join之前所处理的文件要事先经过排序。

1
2
3
4
5
6
7
8
9
$ cat testfile_1
Hello 95 #例如,本例中第一列为姓名,第二列为数额
Linux 85
test 30
cmd@hdd-desktop:~$ cat testfile_2
Hello 2005 #例如,本例中第一列为姓名,第二列为年份
Linux 2009
test 2006
12345678

使用join命令,将两个文件连接:

1
2
3
4
5
$ join testfile_1 testfile_2 #连接testfile_1、testfile_2中的内容  
Hello 95 2005 #连接后显示的内容
Linux 85 2009
test 30 2006
1234

两个文件互换,输出结果的变化:

1
2
3
4
5
$ join testfile_2 testfile_1 #改变文件顺序连接两个文件  
Hello 2005 95 #连接后显示的内容
Linux 2009 85
test 2006 30
1234

参数

  • -a<1或2> 除了显示原来的输出内容之外,还显示指令文件中没有相同栏位的行。

  • -e<字符串> 若[文件1]与[文件2]中找不到指定的栏位,则在输出中填入选项中的字符串。

  • -i或–igore-case 比较栏位内容时,忽略大小写的差异。

  • -o<格式> 按照指定的格式来显示结果。

  • -t<字符> 使用栏位的分隔字符。

  • -v<1或2> 跟-a相同,但是只显示文件中没有相同栏位的行。

  • -1<栏位> 连接[文件1]指定的栏位。

  • -2<栏位> 连接[文件2]指定的栏位。

paste-将多个文件对应行链接在一起

paste 指令会把每个文件以列对列的方式,一列列地加以合并。

语法:

1
2
paste [-s][-d <间隔字符>][文件...]
1

参数

  • -d<间隔字符>或–delimiters=<间隔字符>  用指定的间隔字符取代跳格字符。

  • -s或–serial  串列进行而非平行处理。

  • [文件…] 指定操作的文件路径

使用paste指令将文件"file"、“testfile”、"testfile1"进行合并,输入如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ cat file                  #file文件的内容  
xiongdan 200
lihaihui 233
lymlrl 231
$ cat testfile #testfile文件的内容
liangyuanm ss
$ cat testfile1 #testfile1文件的内容
huanggai 56
zhixi 73
$ paste file testfile testfile1
xiongdan 200 liangyuanm ss huanggai 56
lihaihui 233 zhixi 73
lymlrl 231
$ paste -d ':' file testfile testfile1
xiongdan 200:liangyuanm ss:huanggai 56
lihaihui 233::zhixi 73
lymlrl 231::
1234567891011121314151617

参数"-s"可以将一个文件中的多行数据合并为一行进行显示:

1
2
3
$ paste -s file             #合并指定文件的多行数据
xiongdan 200 lihaihui 233 lymlrl 231
12

如果将文件位置改为-,表示接收标准输入:

1
2
3
4
5
$ cat file |paste testfile1 -
huanggai 56 xiongdan 200
zhixi 73 lihaihui 233
lymlrl 231
1234

split - 文件切割

split命令用于将一个文件分割成数个。

该指令将大文件分割成较小的文件,在默认情况下将按照每1000行切割成一个小文件。

语法:

1
2
3
4
5
split [-bl] file prefix
-b: 以大小切割
-l:以行数切割
prefix:切割后文件的前缀
1234

参数说明

  • -<行数> : 指定每多少行切成一个小文件

  • -b<字节> : 指定每多少字节切成一个小文件

  • -C<字节> : 与参数"-b"相似,但是在切 割时将尽量维持每行的完整性

  • [输出文件名] : 设置切割后文件的前置文件名, split会自动在前置文件名后再加上编号

使用指令"split"将文件"README"每6行切割成一个文件,输入如下命令:

1
2
3
4
5
$ split -6 README       #将README文件每六行分割成一个文件 
$ ls #执行ls指令
#获得当前目录结构
README xaa xad xag xab xae xah xac xaf xai
1234

以上命令执行后,指令"split"会将原来的大文件"README"切割成多个以"x"开头的小文件。而在这些小文件中,每个文件都只有6行内容。

以大小切割:

1
2
3
4
5
6
7
8
9
$ ls -lh disease.dmp
-rwxr-xr-x 1 root root 122M Jul 4 2013 disease.dmp
$ split -b 50m disease.dmp disease.dmp
$ ls -lh disease.dmp*
-rwxr-xr-x 1 root root 122M Jul 4 2013 disease.dmp
-rw-r--r-- 1 root root 50M Jan 9 16:10 disease.dmpaa
-rw-r--r-- 1 root root 50M Jan 9 16:10 disease.dmpab
-rw-r--r-- 1 root root 22M Jan 9 16:10 disease.dmpac
12345678

xargs - 参数代换

不是所有的命令都支持管道,如ls,对于不支持管道的命令,可以通过xargs让其有管道命令的效果,如下所示:

1
2
3
4
5
6
7
8
9
10
# find /sbin -perm +7000 | xargs ls -l
-rwsr-x--- 1 root ecryptfs 19896 Feb 23 2012 /sbin/mount.ecryptfs_private
-rwsr-xr-x 1 root root 75496 Jan 9 2013 /sbin/mount.nfs
-rwsr-xr-x 1 root root 75504 Jan 9 2013 /sbin/mount.nfs4
-rwxr-sr-x 1 root root 8544 Feb 22 2012 /sbin/netreport
-rwsr-xr-x 1 root root 14112 Nov 2 2010 /sbin/pam_timestamp_check
-rwsr-xr-x 1 root root 75504 Jan 9 2013 /sbin/umount.nfs
-rwsr-xr-x 1 root root 75504 Jan 9 2013 /sbin/umount.nfs4
-rwsr-xr-x 1 root root 19768 Nov 2 2010 /sbin/unix_chkpwd
123456789

如果没有xargs,ls -l的结果将不是前面find的标准输出,因为ls不支持管道命令。

xargs 用作替换工具,读取输入数据重新格式化后输出。

定义一个测试文件,内有多行文本数据:

1
2
3
4
5
6
7
# cat test.txt
a b c d e f g
h i j k l m n
o p q
r s t
u v w x y z
123456

多行输入单行输出:

1
2
3
# cat test.txt | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z
12

-n 选项多行输出:

1
2
3
4
5
6
7
8
9
10
11
# cat test.txt | xargs -n3
a b c
d e f
g h i
j k l
m n o
p q r
s t u
v w x
y z
12345678910

-d 选项可以自定义一个定界符:

1
2
3
# echo "nameXnameXnameXname" | xargs -dX
name name name name
12

结合 -n 选项使用:

1
2
3
4
# echo "nameXnameXnameXname" | xargs -dX -n2
name name
name name
123

读取 stdin,将格式化后的参数传递给命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cat sk.sh
#!/bin/bash
#sk.sh命令内容,打印出所有参数。
echo $*
# cat arg.txt
aaa
bbb
ccc
# cat arg.txt | xargs -I {} ./sk.sh -p {} -l
-p aaa -l
-p bbb -l
-p ccc -l
123456789101112

选项-I指定一个替换字符串 {},这个字符串在 xargs 扩展时会被替换掉。

复制所有图片文件到 /data/images 目录下:

1
2
ls *.jpg | xargs -n1 -I {} cp {} /data/images
1

选项-n 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。

xargs 结合 find 使用

用 rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 用 xargs 去避免这个问题:

1
2
find . -type f -name "*.log" -print0 | xargs -0 rm -f
1

xargs -0 将 \0 作为定界符。

统计一个源代码目录中所有 php 文件的行数:

1
2
find . -type f -name "*.php" -print0 | xargs -0 wc -l
1

查找所有的 jpg 文件,并且压缩它们:

1
2
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
1

批量下载:

1
2
# cat url-list.txt | xargs wget -c
1

wget的-c选项表示断点续传。

文本编辑命令

cut命令

1
2
3
4
选项与参数:
-d :后面接分隔字符。与 -f 一起使用;
-f :依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思;
-c :以字符 (characters) 的单位取出固定字符区间;

cut以行为单位,根据分隔符把行分成若干列,这样就可以指定选取哪些列了。

1
2
3
4
5
6
cut -d '分隔字符' -f 选取的列数
echo $PATH|cut -d ':' -f 2 --选取第2列
echo $PATH|cut -d ':' -f 3,5 --选取第3列和第5列
echo $PATH|cut -d ':' -f 3-5 --选取第3列到第5列
echo $PATH|cut -d ':' -f 3- --选取第3列到最后1列
echo $PATH|cut -d ':' -f 1-3,5 --选取第1到第3列还有第5列

只显示/etc/passwd的用户和shell:

1
2
3
4
#cat /etc/passwd | cut -d ':' -f 1,7 
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh

sed命令

sed 可依照脚本的指令来处理、编辑文本文件。

Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

语法:

1
sed [-e<script>][-f<script文件>][文本文件]

参数说明

  • -e <script>以指定的script来处理输入的文本文件。

  • -f<script文件>以指定的script文件来处理输入的文本文件。

  • -n仅显示script处理后的结果,一般跟p动作搭配使用。

  • -i使用处理后的结果修改文件。

动作说明

  • a:在指定行后面插入内容

  • i:在指定行前面插入内容

  • d:删除指定行

  • c :替换指定行

  • p :打印指定行的数据,通常需要跟-n选项搭配使用

  • s :替换指定字符,兼容vim的替换语法,例如 1,20s/old/new/g

元字符集

sed支持一般的正则表达式,下面是支持的正则语法:^行的开始 如:/^sed/匹配所有以sed开头的行。$行的结束 如:/sed$/匹配所有以sed结尾的行。.匹配一个非换行符的任意字符 如:/s.d/匹配s后接一个任意字符,然后是d。*匹配零或多个字符 如:/*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\+重复字符x,至少1次,如:/o\+/匹配至少有1个o的行。x\{m\}重复字符x,m次,如:/o\{5\}/匹配包含5个o的行。x\{m,\}重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。x\{m,n\}重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5-10个o的行。

a|i:在指定行位置添加行

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky8:Corazon]# cat a
LINUX!
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test

[root@rocky8:Corazon]# sed -e 2a\newline a
LINUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test

默认情况下-e参数可以省略:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@rocky8:Corazon]# cat a | sed '2a\newline'
LINUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test
[root@rocky8:~]# sed 2a\newline a
NUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test
[root@rocky8:Corazon]# sed '2a newline' a
LINUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test

在第二行之前添加一行:

1
2
3
4
5
6
[root@rocky8:Corazon]# sed '2i newline' a
LINUX!
newline
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test

最后一行加入 # This is a test:

1
2
3
4
5
6
7
[root@rocky8:Corazon]# sed '$a # This is a test' a
LINUX!
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test

# This is a test

同时添加多行:

1
2
3
4
5
6
7
8
[root@rocky8:Corazon]# cat a|sed '2a\newline1\
> newline2'
LINUX!
Linux is a free unix-type opterating system.
newline1
newline2
This is a linux testfile!
Linux test

d:删除指定行

将 /etc/passwd 的内容列出行号,并将第 2~5 行删除!

1
2
3
4
5
[root@rocky8:~]# nl /etc/passwd|sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
.....(后面省略).....

只删除第2行:

1
nl /etc/passwd | sed '2d' 

删除第3到最后一行:

1
nl /etc/passwd | sed '3,$d' 

删除/etc/passwd所有包含/sbin/nologin的行,其他行输出:

1
2
3
4
5
6
7
8
[root@rocky8:~]# nl /etc/passwd|sed '/\/sbin\/nologin/d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
25 zah:x:1000:1000:Zah:/home/zah:/bin/bash
26 Cora:x:1002:1002::/home/Cora:/bin/bash
27 Corazon:x:1003:1003::/home/Corazon:/bin/bash

c:替换指定行

将第2-5行的内容替换成为『No 2-5 number』:

1
2
3
4
[root@rocky8:~]# nl /etc/passwd|sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync

p:仅显示指定行

不加-n选项时,除了输出匹配行,还同时会输出所有行,所以需要加-n选项。

仅列出 /etc/passwd 文件内的第 5-7 行:

1
2
3
4
[root@rocky8:~]# nl /etc/passwd|sed -n '5,7p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

搜索 /etc/passwd有root关键字的行:

1
2
3
4
5
6
[root@rocky8:~]# cat /etc/passwd|sed -n '/root/p'
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@rocky8:~]# sed -n '/root/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

打印/etc/passwd有以root和bin开头之间的行:

1
2
3
[root@rocky8:~]# sed -n '/^root/,/^bin/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

打印从第五行开始到第一个包含以/usr/games开始的行之间的所有行:

1
2
3
4
5
6
7
8
[root@rocky8:~]# nl /etc/passwd | sed -n '5,\/usr\/games/p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
11 games:x:12:100:games:/usr/games:/sbin/nologin

s:字符串替换

语法:

1
sed 's/要被取代的字串/新的字串/g'

不论什么字符,紧跟着s命令的都被认为是新的分隔符.

sed 's#10#100#g'表示把所有10替换成100,“#”在这里是分隔符,代替了默认的“/”分隔符。

提取本机所有的ip地址:

1
2
3
4
5
6
[root@rocky8:~]# ifconfig | grep 'inet '
inet 10.0.0.191 netmask 255.255.255.0 broadcast 10.0.0.255
inet 127.0.0.1 netmask 255.0.0.0
[root@rocky8:~]# ifconfig | grep 'inet '|sed 's/^[^0-9]*\([0-9\.]*\).*$/\1/g'
10.0.0.191
127.0.0.1

对于以root和bin开头之间的行,每行的末尾添加sed test:

1
2
3
4
5
6
[root@rocky8:~]# cat /etc/passwd | sed '/^root/,/^bin/s/$/--sed test/'
root:x:0:0:root:/root:/bin/bash--sed test
daemon:x:2:2:daemon:/sbin:/sbin/nologin--sed test
bin:x:1:1:bin:/bin:/sbin/nologin--sed test
adm:x:3:4:adm:/var/adm:/sbin/nologin
......

y:单字符替换

跟s一样也用于替换,不过s替换的是整体,y替换的是每一字母对应的单个字母

把data中的第一行至第三行中的a替换成A,b替换成B,c替换成C:

1
sed '1,3y/abc/ABC/' data 

示例:

1
2
3
4
[root@rocky8:~]# echo "123" | sed 'y/13/34/'
324
[root@rocky8:~]# echo "axxbxxcxx" | sed 'y/abc/123/'
1xx2xx3xx

注:单个字符转换用y,字符串转换用's/str1/str2/g'

hHgG模式空间与保持空间

首先介绍一下模式空间和保持空间:

(H、h、G、g、x)
模式空间:sed处理文本内容行的一个临时缓冲区,模式空间中的内容会主动打印到标准输出,并自动清空模式空间

**保持空间:**sed处理文本内容行的另一个临时缓冲区,不同的是保持空间内容不会主动清空,也不会主动打印到标准输出,而是需要sed命令来进行处理

模式空间与保持空间的关系:

**模式空间:**相当于流水线,文本行再模式空间中进行处理;
**保持空间:**相当于仓库,在模式空间对数据进行处理时,可以把数据临时存储到保持空间;作为模式空间的一个辅助临时缓冲区,但又是相互独立,可以进行交互,命令可以寻址模式空间但是不能寻址保持空间。可以使用高级命令h,H,g,G与模式空间进行交互。

实际上, 保持空间是模式空间一个临时存放数据的缓冲区,协助模式空间进行数据处理。

相关命令的作用:

d Delete pattern space. Start next cycle.
删除pattern space的内容,开始下一个循环

h H Copy/append pattern space to hold space.
复制/追加pattern space的内容到hold space.(复制会覆盖原内容)

g G Copy/append hold space to pattern space.
复制/追加hold space的内容到pattern space. (复制会覆盖原内容)

x Exchange the contents of the hold and pattern spaces.
交换hold space和pattern space的内容.

h命令是将当前模式空间中内容覆盖至保持空间,H命令是将当前模式空间中的内容追加至保持空间

g命令是将当前保持空间中内容覆盖至模式空间,G命令是将当前保持空间中的内容追加至模式空间

模拟tac命令:

1
2
3
4
5
6
7
8
9
10
11
12
[root@rocky8:~]# cat num
One
Two
Three
[root@rocky8:~]# tac num
Three
Two
One
[root@rocky8:~]# sed '1!G;h;$!d' num
Three
Two
One

1!G第1行不 执行“G”命令,从第2行开始执行。

$!d,最后一行不删除(保留最后1行)(只有最后一行不删)

原理图:

image-20250219211455837

递增序列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@rocky8:~]# seq 3|sed 'H;g'

1

1
2

1
2
3
[root@rocky8:~]# seq 3|sed '1h;1!H;g'
1
1
2
1
2
3

多次指定-e选项进行多点编辑

删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell:

1
2
3
[root@rocky8:~]# nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
1 root:x:0:0:root:/root:/bin/blueshell
2 daemon:x:2:2:daemon:/sbin:/sbin/nologin

删除一个文件以#开头的行和空行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@rocky8:~]# cat abc

b
a

# aaa

ddd

# sss
eeee


[root@rocky8:~]# sed -e '/^#/d' -e '/^$/d' abc
b
a
ddd
eeee

也可以通过;实现

1
2
3
4
5
6
7
8
[root@rocky8:~]# nl /etc/passwd|sed '3,$d;s/bash/blueshell/' 
1 root:x:0:0:root:/root:/bin/blueshell
2 daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@rocky8:~]# sed '/^#/d;/^$/d' abc
b
a
ddd
eeee

选项-i直接修改文件内容

默认情况下sed命令仅仅只是将处理结果显示在控制台,加-i选项则会修改文件内容。

将 regular_express.txt 内每一行结尾若为 . 则换成 !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@rocky8:~]# cat re
taobao.
google.
taobao.
facebook.
zhihu-
weibo-
[root@rocky8:~]# sed -i 's/\.$/\!/' re
[root@rocky8:~]# cat re
taobao!
google!
taobao!
facebook!
zhihu-
weibo-

awk命令

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

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

语法:

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

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

选项参数说明:

  • -F fs or --field-separator fs
    指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。

  • -v var=value or --asign var=value
    赋值一个用户定义变量。

  • -f scripfile or --file scriptfile
    从脚本文件中读取awk命令。

基本用法

1
awk '{[pattern] action}' file

每行按空格或TAB分割,使用print输出文本中的1、4列:

1
2
3
4
5
6
7
8
9
10
[root@rocky8:~]# cat log
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
[root@rocky8:~]# awk '{print $1,$4}' log
2 a
3 like
This's
10 orange,apple,mongo

使用printf格式化输出:

1
2
3
4
5
[root@rocky8:~]# awk '{printf "%-8s %-10s\n",$1,$4}' log
2 a
3 like
This's
10 orange,apple,mongo
-F指定分割字符
1
awk -F  #-F相当于内置变量FS, 指定分割字

使用:分割,取/etc/passwd文件每个用户对应shell:

1
2
3
4
5
6
7
8
[root@rocky8:~]# awk -F: '{print $1,$7}' /etc/passwd
root /bin/bash
daemon /sbin/nologin
bin /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
......

同时使用:和/l两个分隔符分割/etc/passwd文件

1
2
3
4
5
6
[root@rocky8:~]# awk -F '[:\/]' '{print $1,$7}'  /etc/passwd
awk: warning: escape sequence `\/' treated as plain `/'
root root
daemon sbin
bin bin
......
-v设置变量
1
awk -v  # 设置变量

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@rocky8:~]# cat log
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
[root@rocky8:~]# awk -va=1 '{print $1,$1+a}' log
2 3
3 4
This's 1
10 11
[root@rocky8:~]# awk -va=1 -vb=s '{print $1,$1+a,$1b}' log
2 3 2s
3 4 3s
This's 1 This'ss
10 11 10s
-f指定awk脚本
1
awk -f {awk脚本} {文件名}

脚本模块:

  • BEGIN{ 这里面放的是执行前的语句 }

  • END {这里面放的是处理完所有的行后要执行的语句 }

  • {这里面放的是处理每一行时要执行的语句}

假设有这么一个文件(学生成绩表):

1
2
3
4
5
6
[root@rocky8:~]# cat score
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62

awk脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@rocky8:~]# cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0

printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1,$2,$3,$4,$5,$3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

注:END{}中的NR表示已经读出的记录数,就是行号,从1开始

我们来看一下执行结果:

1
2
3
4
5
6
7
8
9
10
11
[root@rocky8:~]# awk -f cal.awk score
NAME NO. MATH ENGLISH COMPUTER TOTAL
---------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
---------------------------------------------
TOTAL: 319 393 350
AVERAGE: 63.80 78.60 70.00

AWK工作原理

AWK 工作流程可分为三个部分:

  • 读输入文件之前执行的代码段(由BEGIN关键字标识)。

  • 主循环执行输入文件的代码段。

  • 读输入文件之后的代码段(由END关键字标识)。

命令结构:

1
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

下面的流程图描述出了 AWK 的工作流程:

img

  • 1、通过关键字 BEGIN 执行 BEGIN 块的内容,即 BEGIN 后花括号 {} 的内容。

  • 2、完成 BEGIN 块的执行,开始执行body块。

  • 3、读入有 \n 换行符分割的记录。

  • 4、将记录按指定的域分隔符划分域,填充域,$0 则表示所有域(即一行内容),**1表示第一个域,∗∗n表示第 n 个域。

  • 5、依次执行各 BODY 块,pattern 部分匹配该行内容成功后,才会执行 awk-commands 的内容。

  • 6、循环读取并执行各行直到文件结束,完成body块执行。

  • 7、开始 END 块执行,END 块可以输出最终结果。

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

过滤第一列大于2的行

1
2
3
4
[root@rocky8:~]# awk '$1>2' log
3 Are you like awk
This's a test
10 There are orange,apple,mongo

过滤第一列等于2的行

1
2
[root@rocky8:~]# awk '$1==2 {print $1,$3}' log 
2 is

过滤第一列大于2并且第二列等于’Are’的行

1
2
[root@rocky8:~]# awk '$1>2 && $2=="Are" {print $1,$2,$3}' log
3 Are you

内建变量

变量描述
$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)

格式化变量说明:

  • %s 输出字符串

  • %i 输出整数

  • %f 输出浮点数

%-5s 格式为左对齐且宽度为5的字符串代替(-表示左对齐),不使用则是又对齐。
%-4.2f 格式为左对齐宽度为4,保留两位小数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@rocky8:~]# awk 'BEGIN{printf "%8s %8s %8s %8s %8s %8s %8s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS";printf "---------------------------------------------\n"} {printf "%8s %8s %8s %8s %8s %8s %8s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS}'  log
FILENAME ARGC FNR FS NF NR OFS
---------------------------------------------
log 2 1 5 1
log 2 2 5 2
log 2 3 3 3
log 2 4 4 4

[root@rocky8:~]# awk -F: 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log
FILENAME ARGC FNR FS NF NR OFS ORS RS
---------------------------------------------
log 2 1 : 1 1


log 2 2 : 1 2


log 2 3 : 1 3


log 2 4 : 1 4


输出顺序号 NR, 匹配文本行号
1
2
3
4
5
[root@rocky8:~]# awk '{print NR,FNR,$1,$2,$3}' log
1 1 2 this is
2 2 3 Are you
3 3 This's a test
4 4 10 There are
指定输出分割符
1
2
3
4
5
6
7
8
9
10
11
python@ubuntu:~/test$ cat log.txt 
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
python@ubuntu:~/test$ awk '{print $1,$2,$5}' OFS=" $ " log.txt
2 $ this $ test
3 $ Are $ awk
This's $ a $
10 $ There $
12345678910
忽略大小写
1
2
3
4
5
$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt
---------------------------------------------
2 this is a test
This's a test
1234

RS,ORS,FS,OFS区别与联系

学习awk时,一定要记得动手去实践,只有在实践中才能发现问题,以下就我在学习中和实践中的经验,总结一下RS,ORS,FS,OFS的区别和联系。

一,RS与ORS

1,RS是记录分隔符,默认的分隔符是\n,具体用法看下

1
2
3
4
[root@rocky8:~]# cat test1
111 222
333 444
555 666

2,RS默认分割符\n

1
2
3
4
[root@rocky8:~]# awk '{print $0}' test1  //awk 'BEGIN{RS="\n"}{print $0}' test1 这二个是一样的
111 222
333 444
555 666

其实你可以把上面test1文件里的内容理解为,111 222\n333 444\n555 6666,利用\n进行分割。看下一个例子

3,自定义RS分割符

1
2
3
4
5
[root@rocky8:~]# echo "111 222|333 444|555 666"|awk 'BEGIN{RS="|"}{print $0,RT}'
111 222 |
333 444 |
555 666

结合上面一个例子,就很容易理解RS的用法了。

4,RS也可能是正则表达式

1
2
3
4
[root@rocky8:~]# echo "111 222a333 444b555 666"|awk 'BEGIN{RS="[a-z]+"}{print $1,RS,RT}'
111 [a-z]+ a
333 [a-z]+ b
555 [a-z]+

从例3和例4,我们可以发现一点,当RT是利用RS匹配出来的内容。如果RS是某个固定的值时,RT就是RS的内容

5,RS为空时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@rocky8:~]# cat -n test2
1 111 222
2
3 333 444
4 333 444
5
6
7 555 666
[root@rocky8:~]# awk 'BEGIN{RS=""}{print $0}' test2
111 222
333 444
333 444
555 666
[root@rocky8:~]# awk 'BEGIN{RS=""}{print "<",$0,">"}' test2
< 111 222 >
< 333 444 //这一行和下面一行,是一行
333 444 >
< 555 666 >

6,ORS记录输出分符符,默认值是\n

把ORS理解成RS反过程,这样更容易记忆和理解,看下面的例子。

1
2
3
4
5
6
[root@rocky8:~]# awk 'BEGIN{ORS="\n"}{print $0}' test1 //awk '{print $0}' test1二者是一样的
111 222
333 444
555 666
[root@rocky8:~]# awk 'BEGIN{ORS="|"}{print $0}' test1
111 222|333 444|555 666|[root@rocky8:~]#

二,FS与OFS(不理解)

1,FS指定列分割符

1
2
3
4
[root@rocky8:~]# echo "111|222|333"|awk '{print $1}' 
111|222|333
[root@rocky8:~]# echo "111|222|333"|awk 'BEGIN{FS="|"}{print $1}'
111

2,FS也可以用正则

1
2
[root@rocky8:~]# echo "111||222|333"|awk 'BEGIN{FS="[|]+"}{print $1}'  
111

3,FS为空的时候(不理解为啥要NF++)

1
2
[root@rocky8:~]# echo "111|222|333"|awk 'BEGIN{FS=""}{NF++;print $0}'
1 1 1 | 2 2 2 | 3 3 3

当FS为空的时候,awk会把一行中的每个字符,当成一列来处理

4,RS被设定成非\n时,\n会成FS分割符中的一个

1
2
3
4
5
6
7
[root@rocky8:~]# cat test1
111 222
333 444
555 666
[root@rocky8:~]# awk 'BEGIN{RS="444";}{print $2,$3}' test1
222 333
666

222和333之间是有一个\n的,当RS设定成444后,222和333被认定成同一行的二列了,其实按常规思想是二行的一列才对

5,OFS列输出分隔符

1
2
3
4
5
6
7
8
[root@rocky8:~]# awk 'BEGIN{OFS="|";}{print $1,$2}' test1
111|222
333|444
555|666
[root@rocky8:~]# awk 'BEGIN{OFS="|";}{print $1 OFS $2}' test1
111|222
333|444
555|666

test1只有二列,如果100列,都写出来太麻烦了吧。

1
2
3
4
5
6
7
8
[root@rocky8:~]# awk 'BEGIN{OFS="|";}{print $0}' test1  
111 222
333 444
555 666
[root@rocky8:~]# awk 'BEGIN{OFS="|";}{NF=NF;print $0}' test1
111|222
333|444
555|666

为什么第二种方法中的OFS生效呢?个人觉得,awk觉查到列有所变化时,就会让OFS生效,没变化直接输出了。

此部分转自:海底苍鹰:awk中RS,ORS,FS,OFS区别与联系

正则字符串匹配

~ 表示模式开始。// 中是模式。

输出第二列包含 “th”,并打印第二列与第四列:

1
2
[root@rocky8:~]# awk '$2 ~ /th/ {print $2,$4}' log 
this a

输出包含"re"的行:

1
2
3
[root@rocky8:~]# awk '/re/ {print $0}' log 
3 Are you like awk
10 There are orange,apple,mongo

!表示取反

输出第二列不包含 “th”,并打印第二列与第四列:

1
2
3
4
[root@rocky8:~]# awk '$2 !~ /th/ {print $0}' log 
3 Are you like awk
This's a test
10 There are orange,apple,mongo

输出不包含"re"的行:

1
2
3
[root@rocky8:~]# awk '!/re/ {print $0}' log 
2 this is a test
This's a test

一些实例

计算文件大小

1
2
[root@rocky8:~]# ls -l | awk '{sum+=$5}END{print sum}'
1066

从文件中找出长度大于80的行

1
awk 'length>80' log
1
2
3
4
5
6
7
8
9
[root@rocky8:~]# seq 100|sed ":a;N;s/\n//g;ta" >> log
[root@rocky8:~]# cat log
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
[root@rocky8:~]# awk 'length>80' log
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100

打印九九乘法表

1
seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}'

访问日志分析

日志格式

1
2
[root@rocky8:~]# head access.log -n1
42.236.10.75 "changtou.xiaoxiaoming.xyz" [14/Oct/2019:12:47:18 +0800] "GET /logo/8@3x.png HTTP/1.1" 200 26053 "https://changtou.xiaoxiaoming.xyz/" "Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; EML-AL00 Build/HUAWEIEML-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 baidu.sogo.uc.UCBrowser/11.9.4.974 UWS/2.13.1.48 Mobile Safari/537.36 AliApp(DingTalk/4.5.11) com.alibaba.android.rimet/10487439 Channel/227200 language/zh-CN" "42.236.10.75" rt="0.000" uct="-" uht="-" urt="-"

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.数据清洗
awk '($6 ~ /.html/) && ($8 ~ /200/) {print $0}' access.log > clean.log

2.统计PV
[root@rocky8:~]# awk '{print $0}' clean.log | wc -l
700
[root@rocky8:~]# cut -d ' ' -f 1 clean.log|wc -l
700

3:UV
[root@rocky8:~]# awk '{print $1}' clean.log |sort|uniq| wc -l
155
[root@rocky8:~]# cut -d ' ' -f 1 clean.log|sort|uniq| wc -l
155

4:获取每天访问网站最多的前10名用户
awk '{print $1}' clean.log|sort|uniq -c|sort -k 1nr|head

cut -d ' ' -f 1 clean.log|sort|uniq -c|sort -k 1nr|head

awk编程

条件语句IF&ELSE

IF 条件语句语法格式如下:

1
2
if (condition)
action

也可以使用花括号来执行一组操作:

1
2
3
4
5
6
7
8
if (condition)
{
action-1
action-2
.
.
action-n
}

判断数字是奇数还是偶数:

1
2
[root@rocky8:~]# awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d 是偶数\n", num }'
10 是偶数

IF - ELSE 条件语句语法格式如下:

1
2
3
4
5
if (condition)
action-1
else
action-2
1234

在条件语句 condition 为 true 时只需 action-1,否则执行 action-2。

1
2
3
4
5
6
7
8
[root@rocky8:~]# awk 'BEGIN {
> num = 11;
> if (num % 2 == 0) printf "%d 是偶数\n", num;
> else printf "%d 是奇数\n", num
> }'
11 是奇数
[root@rocky8:~]# awk 'BEGIN {num = 11; if (num % 2 == 0) printf "%d 是偶数\n", num; else printf "%d 是奇数\n", num }'
11 是奇数

可以创建多个 IF - ELSE 格式的判断语句来实现多个条件的判断:

1
2
3
4
5
6
7
8
9
$ awk 'BEGIN {
a=30;
if (a==10)
print "a = 10";
else if (a == 20)
print "a = 20";
else if (a == 30)
print "a = 30";
}'

输出结果:

1
2
3
4
5
6
7
8
9
10
[root@rocky8:~]# awk 'BEGIN {
> a=30;
> if (a==10)
> print "a = 10";
> else if (a == 20)
> print "a = 20";
> else if (a == 30)
> print "a = 30";
> }'
a = 30

循环语句For&While

For 循环的语法如下:

1
2
for (initialisation; condition; increment/decrement)
action

下面的例子使用 For 循环输出数字 1 至 5:

1
2
3
4
5
6
python@ubuntu:~/test$ awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
1
2
3
4
5

While 循环的语法如下:

1
2
while (condition)
action

下面是使用 While 循环输出数字 1 到 5 的例子:

1
2
3
4
5
6
python@ubuntu:~/test$ awk 'BEGIN {i = 1; while (i < 6) { print i; ++i } }'
1
2
3
4
5

在下面的示例子中,当计算的和大于 50 的时候使用 break 结束循环:

1
2
3
4
5
$ awk 'BEGIN {
sum = 0; for (i = 0; i < 20; ++i) {
sum += i; if (sum > 50) break; else print "Sum =", sum
}
}'

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
python@ubuntu:~/test$ awk 'BEGIN {
> sum = 0; for (i = 0; i < 20; ++i) {
> sum += i; if (sum > 50) break; else print "Sum =", sum
> }
> }'
Sum = 0
Sum = 1
Sum = 3
Sum = 6
Sum = 10
Sum = 15
Sum = 21
Sum = 28
Sum = 36
Sum = 45

Continue 语句用于在循环体内部结束本次循环,从而直接进入下一次循环迭代。

下面的例子输出 1 到 20 之间的偶数:

1
2
3
4
5
6
7
8
9
10
11
python@ubuntu:~/test$ awk 'BEGIN {for (i = 1; i <= 20; ++i) {if (i % 2 == 0) print i ; else continue} }'
2
4
6
8
10
12
14
16
18
20

Exit 用于结束脚本程序的执行。

该函数接受一个整数作为参数表示 AWK 进程结束状态。 如果没有提供该参数,其默认状态为 0。

下面例子中当和大于 50 时结束 AWK 程序。

1
2
3
4
5
$ awk 'BEGIN {
sum = 0; for (i = 0; i < 20; ++i) {
sum += i; if (sum > 50) exit(10); else print "Sum =", sum
}
}'

输出结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
python@ubuntu:~/test$ awk 'BEGIN {
> sum = 0; for (i = 0; i < 20; ++i) {
> sum += i; if (sum > 50) exit(10); else print "Sum =", sum
> }
> }'
Sum = 0
Sum = 1
Sum = 3
Sum = 6
Sum = 10
Sum = 15
Sum = 21
Sum = 28
Sum = 36
Sum = 45
python@ubuntu:~/test$ echo $?
10

awk数组

AWK的数组底层数据结构是散列表,索引可以是数字或字符串。

数组使用的语法格式:

1
array_name[index]=value

创建数组并访问数组元素:

1
2
3
4
5
$ awk 'BEGIN {
sites["taobao"]="www.taobao.com";
sites["google"]="www.google.com"
print sites["taobao"] "\n" sites["google"]
}'

删除数组元素语法格式:

1
delete array_name[index]

下面的例子中,数组中的 google 元素被删除(删除命令没有输出):

1
2
3
4
5
6
$ awk 'BEGIN {
sites["taobao"]="www.taobao.com";
sites["google"]="www.google.com"
delete sites["google"];
print sites["google"]
}'

AWK 本身不支持多维数组,不过我们可以很容易地使用一维数组模拟实现多维数组。

如下示例为一个 3x3 的三维数组:

1
2
3
100 200 300
400 500 600
700 800 900

以上实例中,array[0][0] 存储 100,array[0][1] 存储 200 ,依次类推。为了在 array[0][0] 处存储 100, 可以使用字符串0,0 作为索引: array[“0,0”] = 100。

下面是模拟二维数组的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ awk 'BEGIN {
array["0,0"] = 100;
array["0,1"] = 200;
array["0,2"] = 300;
array["1,0"] = 400;
array["1,1"] = 500;
array["1,2"] = 600;
# 输出数组元素
print "array[0,0] = " array["0,0"];
print "array[0,1] = " array["0,1"];
print "array[0,2] = " array["0,2"];
print "array[1,0] = " array["1,0"];
print "array[1,1] = " array["1,1"];
print "array[1,2] = " array["1,2"];
}'

执行上面的命令可以得到如下结果:

1
2
3
4
5
6
array[0,0] = 100
array[0,1] = 200
array[0,2] = 300
array[1,0] = 400
array[1,1] = 500
array[1,2] = 600

在数组上可以执行很多操作,比如,使用 asort 完成数组元素的排序,或者使用 asorti 实现数组索引的排序等等。

AWK 用户自定义函数

自定义函数的语法格式为:

1
2
3
4
function function_name(argument1, argument2, ...)
{
function body
}

以下实例实现了两个简单函数,它们分别返回两个数值中的最小值和最大值。

文件 functions.awk 代码如下:

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
# 返回最小值
function find_min(num1, num2)
{
if (num1 < num2)
return num1
return num2
}

# 返回最大值
function find_max(num1, num2)
{
if (num1 > num2)
return num1
return num2
}

# 主函数
function main(num1, num2)
{
# 查找最小值
result = find_min(10, 20)
print "Minimum =", result

# 查找最大值
result = find_max(10, 20)
print "Maximum =", result
}

# 脚本从这里开始执行
BEGIN {
main(10, 20)
}

执行 functions.awk 文件,可以得到如下的结果:

1
2
3
$ awk -f functions.awk 
Minimum = 10
Maximum = 20

AWK 内置函数

AWK 内置函数主要有以下几种:

  • 算数函数

  • 字符串函数

  • 时间函数

  • 位操作函数

  • 其它函数

算数函数

函数名说明实例
atan2( y, x )返回 y/x 的反正切。$ awk 'BEGIN { PI = 3.14159265 x = -10 y = 10 result = atan2 (y,x) * 180 / PI; printf "The arc tangent for (x=%f, y=%f) is %f degrees\n", x, y, result }'输出结果为:The arc tangent for (x=-10.000000, y=10.000000) is 135.000000 degrees
cos( x )返回 x 的余弦;x 是弧度。$ awk 'BEGIN { PI = 3.14159265 param = 60 result = cos(param * PI / 180.0); printf "The cosine of %f degrees is %f.\n", param, result }'输出结果为:The cosine of 60.000000 degrees is 0.500000.
sin( x )返回 x 的正弦;x 是弧度。$ awk 'BEGIN { PI = 3.14159265 param = 30.0 result = sin(param * PI /180) printf "The sine of %f degrees is %f.\n", param, result }'输出结果为:The sine of 30.000000 degrees is 0.500000.
exp( x )返回 x 幂函数。$ awk 'BEGIN { param = 5 result = exp(param); printf "The exponential value of %f is %f.\n", param, result }'输出结果为:The exponential value of 5.000000 is 148.413159.
log( x )返回 x 的自然对数。$ awk 'BEGIN { param = 5.5 result = log (param) printf "log(%f) = %f\n", param, result }'输出结果为:log(5.500000) = 1.704748
sqrt( x )返回 x 平方根。$ awk 'BEGIN { param = 1024.0 result = sqrt(param) printf "sqrt(%f) = %f\n", param, result }'输出结果为:sqrt(1024.000000) = 32.000000
int( x )返回 x 的截断至整数的值。$ awk 'BEGIN { param = 5.12345 result = int(param) print "Truncated value =", result }'输出结果为:Truncated value = 5
rand( )返回任意数字 n,其中 0 <= n < 1。$ awk 'BEGIN { print "Random num1 =" , rand() print "Random num2 =" , rand() print "Random num3 =" , rand() }'输出结果为:Random num1 = 0.237788 Random num2 = 0.291066 Random num3 = 0.845814
srand( [Expr] )将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。$ awk 'BEGIN { param = 10 printf "srand() = %d\n", srand() printf "srand(%d) = %d\n", param, srand(param) }'输出结果为:srand() = 1 srand(10) = 1417959587
字符串函数
函数说明实例
gsub( Ere, Repl, [ In ] )gsub 是全局替换( global substitution )的缩写。除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行。$ awk 'BEGIN { str = "Hello, World" print "String before replacement = " str gsub("World", "Jerry", str) print "String after replacement = " str }'输出结果为:String before replacement = Hello, World String after replacement = Hello, Jerry
sub(regex,sub,string)sub 函数执行一次子串替换。它将第一次出现的子串用 regex 替换。第三个参数是可选的,默认为 $0。$ awk 'BEGIN { str = "Hello, World" print "String before replacement = " str sub("World", "Jerry", str) print "String after replacement = " str }'输出结果为:String before replacement = Hello, World String after replacement = Hello, Jerry
substr(str, start, l)substr 函数返回 str 字符串中从第 start 个字符开始长度为 l 的子串。如果没有指定 l 的值,返回 str 从第 start 个字符开始的后缀子串。$ awk 'BEGIN { str = "Hello, World !!!" subs = substr(str, 1, 5) print "Substring = " subs }'输出结果为:Substring = Hello
index( String1, String2 )在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从 1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。$ awk 'BEGIN { str = "One Two Three" subs = "Two" ret = index(str, subs) printf "Substring \"%s\" found at %d location.\n", subs, ret }'输出结果为:Substring "Two" found at 5 location.
length [(String)]返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。$ awk 'BEGIN { str = "Hello, World !!!" print "Length = ", length(str) }'输出结果为:Substring "Two" found at 5 location.
blength [(String)]返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。
substr( String, M, [ N ] )返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M 参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N 参数,则子串的长度将是 M 参数指定的位置到 String 参数的末尾 的长度。$ awk 'BEGIN { str = "Hello, World !!!" subs = substr(str, 1, 5) print "Substring = " subs }'输出结果为:Substring = Hello
match( String, Ere )在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。$ awk 'BEGIN { str = "One Two Three" subs = "Two" ret = match(str, subs) printf "Substring \"%s\" found at %d location.\n", subs, ret }'输出结果为:Substring "Two" found at 5 location.
split( String, A, [Ere] )将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。$ awk 'BEGIN { str = "One,Two,Three,Four" split(str, arr, ",") print "Array contains following values" for (i in arr) { print arr[i] } }'输出结果为:Array contains following values One Two Three Four
tolower( String )返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。$ awk 'BEGIN { str = "HELLO, WORLD !!!" print "Lowercase string = " tolower(str) }'输出结果为:Lowercase string = hello, world !!!
toupper( String )返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。$ awk 'BEGIN { str = "hello, world !!!" print "Uppercase string = " toupper(str) }'输出结果为:Uppercase string = HELLO, WORLD !!!
sprintf(Format, Expr, Expr, . . . )根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。$ awk 'BEGIN { str = sprintf("%s", "Hello, World !!!") print str }'输出结果为:Hello, World !!!
strtonum(str)strtonum 将字符串 str 转换为数值。 如果字符串以 0 开始,则将其当作十进制数;如果字符串以 0x 或 0X 开始,则将其当作十六进制数;否则,将其当作浮点数。$ awk 'BEGIN { print "Decimal num = " strtonum("123") print "Octal num = " strtonum("0123") print "Hexadecimal num = " strtonum("0x123") }'输出结果为:Decimal num = 123 Octal num = 83 Hexadecimal num = 291

**注:**Ere 部分可以是正则表达式。

1、gsub、sub 使用

1
2
$ awk 'BEGIN{info="this is a test2012test!";gsub(/[0-9]+/,"||",info);print info}'
this is a test||test!

2、查找字符串(index 使用)

使用了三元运算符: 表达式 ? 动作1 : 动作2

1
2
3
4
5
6
$ awk 'BEGIN{info="this is a test2012test!";print index(info,"11111")?"ok":"no found";}'
no found
$ awk 'BEGIN{info="this is a test2012test!";print index(info,"is")?"ok":"no found";}'
ok
$ awk 'BEGIN{info="this is a test2012test!";print index(info,"test")?"ok":"no found";}'
ok

3、正则表达式匹配查找(match 使用)

1
2
$ awk 'BEGIN{info="this is a test2012test!";print match(info,/[0-9]+/)?"ok":"no found";}'
ok

4、截取字符串(substr使用)

从第 4 个 字符开始,截取 10 个长度字符串。

1
2
$ awk 'BEGIN{info="this is a test2012test!";print substr(info,4,10);}'
s is a tes

5、字符串分割(split使用)

1
2
3
4
5
6
$ awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}'
4
2 is
3 a
4 test
1 this

分割 info,将 info 字符串使用空格切分为动态数组 tA。注意 awk for …in 循环,是一个无序的循环。 并不是从数组下标 1…n ,因此使用时候需要特别注意。

时间函数
函数名说明实例
mktime( YYYY MM DD HH MM SS[ DST])生成时间格式$ awk 'BEGIN { print "Number of seconds since the Epoch = " mktime("2014 12 14 30 20 10") }'输出结果为:Number of seconds since the Epoch = 1418604610
strftime([format [, timestamp]])格式化时间输出,将时间戳转为时间字符串 具体格式,见下表.$ awk 'BEGIN { print strftime("Time = %m/%d/%Y %H:%M:%S", systime()) }'输出结果为:Time = 12/14/2014 22:08:42
systime()得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数awk 'BEGIN{now=systime();print now}'输出结果为:1343210982

strftime 日期和时间格式说明符:

序号描述
%a星期缩写(Mon-Sun)。
%A星期全称(Monday-Sunday)。
%b月份缩写(Jan)。
%B月份全称(January)。
%c本地日期与时间。
%C年份中的世纪部分,其值为年份整除100。
%d十进制日期(01-31)
%D等价于 %m/%d/%y.
%e日期,如果只有一位数字则用空格补齐
%F等价于 %Y-%m-%d,这也是 ISO 8601 标准日期格式。
%gISO8610 标准周所在的年份模除 100(00-99)。比如,1993 年 1 月 1 日属于 1992 年的第 53 周。所以,虽然它是 1993 年第 1 天,但是其 ISO8601 标准周所在年份却是 1992。同样,尽管 1973 年 12 月 31 日属于 1973 年但是它却属于 1994 年的第一周。所以 1973 年 12 月 31 日的 ISO8610 标准周所在的年是 1974 而不是 1973。
%GISO 标准周所在年份的全称。
%h等价于 %b.
%H用十进制表示的 24 小时格式的小时(00-23)
%I用十进制表示的 12 小时格式的小时(00-12)
%j一年中的第几天(001-366)
%m月份(01-12)
%M分钟数(00-59)
%n换行符 (ASCII LF)
%p十二进制表示法(AM/PM)
%r十二进制表示法的时间(等价于 %I:%M:%S %p)。
%R等价于 %H:%M。
%S时间的秒数值(00-60)
%t制表符 (tab)
%T等价于 %H:%M:%S。
%u以数字表示的星期(1-7),1 表示星期一。
%U一年中的第几个星期(第一个星期天作为第一周的开始),00-53
%V一年中的第几个星期(第一个星期一作为第一周的开始),01-53。
%w以数字表示的星期(0-6),0表示星期日 。
%W十进制表示的一年中的第几个星期(第一个星期一作为第一周的开始),00-53。
%x本地日期表示
%X本地时间表示
%y年份模除 100。
%Y十进制表示的完整年份。
%z时区,表示格式为+HHMM(例如,格式要求生成的 RFC 822或者 RFC 1036 时间头)
%Z时区名称或缩写,如果时区待定则无输出。
位操作函数
函数名说明实例
and位与操作。$ awk 'BEGIN { num1 = 10 num2 = 6 printf "(%d AND %d) = %d\n", num1, num2, and(num1, num2) }'输出结果为:(10 AND 6) = 2
compl按位求补。$ awk 'BEGIN { num1 = 10 printf "compl(%d) = %d\n", num1, compl(num1) }'输出结果为:compl(10) = 9007199254740981
lshift左移位操作$ awk 'BEGIN { num1 = 10 printf "lshift(%d) by 1 = %d\n", num1, lshift(num1, 1) }'输出结果为:lshift(10) by 1 = 20
rshift右移位操作$ awk 'BEGIN { num1 = 10 printf "rshift(%d) by 1 = %d\n", num1, rshift(num1, 1) }'输出结果为:rshift(10) by 1 = 5
or按位或操作$ awk 'BEGIN { num1 = 10 num2 = 6 printf "(%d OR %d) = %d\n", num1, num2, or(num1, num2) }'输出结果为:(10 OR 6) = 14
xor按位异或操作$ awk 'BEGIN { num1 = 10 num2 = 6 printf "(%d XOR %d) = %d\n", num1, num2, xor(num1, num2) }'输出结果为:(10 bitwise xor 6) = 12
其他函数
函数名说明实例
close(expr)关闭管道的文件`$ awk 'BEGIN { cmd = “tr [a-z] [A-Z]” print “hello, world !!!”
delete用于从数组中删除元素$ awk 'BEGIN { arr[0] = "One" arr[1] = "Two" arr[2] = "Three" arr[3] = "Four" print "Array elements before delete operation:" for (i in arr) { print arr[i] } delete arr[0] delete arr[1] print "Array elements after delete operation:" for (i in arr) { print arr[i] } }'输出结果为:Array elements before delete operation: One Two Three Four Array elements after delete operation: Three Four
exit终止脚本执行,它可以接受可选的参数 expr 传递 AWK 返回状态。$ awk 'BEGIN { print "Hello, World !!!" exit 10 print "AWK never executes this statement." }'输出结果为:Hello, World !!!
flush刷新打开文件或管道的缓冲区
getline读入下一行使用 getline 从文件 marks.txt 中读入一行并输出:$ awk '{getline; print $0}' marks.txt,AWK 从文件 marks.txt 中读入一行存储到变量 0 中。在下一条语句中,我们使用 getline 读入下一行。因此AWK读入第二行并存储到 0 中。最后,AWK 使用 print 输出第二行的内容。这个过程一直到文件结束。
next停止处理当前记录,并且进入到下一条记录的处理过程。当模式串匹配成功后程序并不执行任何操作:$ awk '{if ($0 ~/Shyam/) next; print $0}' marks.txt
nextfile停止处理当前文件,从下一个文件第一个记录开始处理。首先创建两个文件。 file1.txt 内容如下:file1:str1 file1:str2 file1:str3 file1:str4文件 file2.txt 内容如下:file2:str1 file2:str2 file2:str3 file2:str4现在我们来测试 nextfile 函数。$ awk '{ if ($0 ~ /file1:str2/) nextfile; print $0 }' file1.txt file2.txt输出结果为:file1:str1 file2:str1 file2:str2 file2:str3 file2:str4
return从用户自定义的函数中返回值。请注意,如果没有指定返回值,那么的返回值是未定义的。创建文件 functions.awk,内容如下:function addition(num1, num2) { result = num1 + num2 return result } BEGIN { res = addition(10, 20) print "10 + 20 = " res }执行该文件:$ awk -f functions.awk 10 + 20 = 30
system执行特定的命令然后返回其退出状态。返回值为 0 表示命令执行成功;非 0 表示命令执行失败。$ awk 'BEGIN { ret = system("date"); print "Return value = " ret }'输出结果为:Sun Dec 21 23:16:07 IST 2014 Return value = 0

本文参考:

linux三剑客sed之模式空间与保持空间

用户管理

用户管理包括用户与组账号的管理。

在Unix/Linux系统中,不论是由本机或是远程登录系统,每个系统都必须拥有一个账号,并且对于不同的系统资源拥有不同的使用权限。

Unix/Linux系统中的root账号通常用于系统的维护和管理,它对Unix/Linux操作系统的所有部分具有不受限制的访问权限。

在Unix/Linux安装的过程中,系统会自动创建许多用户账号,而这些默认的用户就称为“标准用户”。

在大多数版本的Unix/Linux中,都不推荐直接使用root账号登录系统。

whoami:查看当前用户

查看当前系统当前账号的用户名。可通过cat /etc/passwd查看系统用户信息。

1
2
[Corazon@rocky8:~]$ whoami
Corazon

who:查看登录用户

who命令用于查看当前所有登录系统的用户信息。

1
2
3
[Corazon@rocky8:~]$ who
root tty1 2025-02-19 12:30
root pts/0 2025-02-19 13:17 (10.0.0.1)

常用选项:

选项含义
-m或am I只显示运行who命令的用户名、登录终端和登录时间
-q或–count只显示用户的登录账号和登录用户的数量
-u在登录时间后显示该用户最后一次操作到当前的时间间隔
–heading显示列标题
-u显示PID

exit:退出登录账户

如果是图形界面,退出当前终端;

如果是使用ssh远程登录,退出登陆账户;

如果是切换后的登陆用户,退出则返回上一个登陆账号。

useradd:添加用户账号

在Unix/Linux中添加用户账号可以使用adduser或useradd命令,因为adduser命令是指向useradd命令的一个链接,因此,这两个命令的使用格式完全一样。

useradd命令的使用格式如下: useradd [参数] 新建用户账号

参数含义
-d指定用户登录系统时的主目录
-m自动建立目录,未指定-d参数时会在/home/{当前用户}目录下建立主目录
-g指定组名称

相关说明:

  • Linux每个用户都要有一个主目录,主目录就是第一次登陆系统,用户的默认当前目录(/home/用户);

  • 每一个用户必须有一个主目录,所以用useradd创建用户的时候,一定给用户指定一个主目录;

  • 如果创建用户的时候,不指定组名,那么系统会自动创建一个和用户名一样的组名。

  • 使用user创建账户后需要使用命令passwd 新建用户为新账户设置密码后才能登陆

若创建用户时未指定家目录,后期可通过usermod -d /home/abc abc指定

命令含义
useradd -d /home/abc abc -m创建abc用户,如果/home/abc目录不存在,就自动创建这个目录,同时用户属于abc组
useradd -d /home/a a -g test -m创建一个用户名字叫a,主目录在/home/a,如果主目录不存在,就自动创建主目录,同时用户属于test组
cat /etc/passwd查看系统当前用户名

设置用户密码:passwd

超级用户可以为自己和其他用户指定口令,普通用户只能用它修改自己的口令。命令的格式为:

1
passwd 选项 用户名

可使用的选项:

  • -l 锁定口令,即禁用账号。

  • -u 口令解锁。

  • -d 使账号无口令。

  • -f 强迫用户下次登录时修改口令。

普通用户修改自己的口令时,passwd命令会先询问原口令,验证后再要求用户输入两遍新口令,如果两次输入的口令一致,则将这个口令指定给用户;而超级用户为用户指定口令时,就不需要知道原口令。

假设当前用户是sam,则下面的命令修改该用户自己的口令:

1
2
3
4
$ passwd 
Old password:******
New password:*******
Re-enter new password:*******

如果是超级用户,可以用下列形式指定任何用户的口令:

1
2
3
# passwd sam 
New password:*******
Re-enter new password:*******

使用root账户为用户指定空口令时,执行下列形式的命令:

1
passwd -d sam

此命令将用户 sam 的口令删除,这样用户 sam 下一次登录时,系统就不再允许该用户登录了。

passwd 命令还可以用 -l(lock) 选项锁定某一用户,使其不能登录,例如:

1
passwd -l sam

usermod:修改用户

常用的选项包括-c, -d, -m, -g, -G, -s, -u以及-o等,这些选项的意义与useradd命令中的选项一样,可以为用户指定新的资源值 。

修改用户所在组:usermod -g 用户组 用户名

1
usermod -g test abc

改abc用户的家目录位置:usermod -d 家目录 用户名

1
usermod -d /home/abc abc

选项-l 新用户名指定一个新的账号,可修改用户名:

1
2
3
4
5
python@ubuntu:~/txt$ tail /etc/passwd -n 1 
aaa:x:1001:1001::/home/aaa:
python@ubuntu:~/txt$ sudo usermod -l bbb -d /home/bbb aaa
python@ubuntu:~/txt$ tail /etc/passwd -n 1
bbb:x:1001:1001::/home/bbb:

删除用户:userdel

命令含义
userdel abc(用户名)删除abc用户,但不会自动删除用户的主目录
userdel -r abc(用户名)删除用户,同时删除用户的主目录

切换用户:su

su后面可以加“-”会将当前的工作目录自动转换到切换后的用户主目录.

命令含义
su切换到root用户
su root切换到root用户
su -切换到root用户,同时切换目录到/root
su - root切换到root用户,同时切换目录到/root
su 普通用户切换到普通用户
su - 普通用户切换到普通用户,同时切换普通用户所在的目录

注意:对于ubuntu平台,只能通过sudo su进入root账号。

sudo允许系统管理员让普通用户执行一些或者全部的root命令的一个工具。

sudo:以root身份执行指令

sudo命令可以临时获取root权限

使用权限:在 /etc/sudoers 中有出现的使用者。

1
2
3
4
显示出自己(执行 sudo 的使用者)的权限
sudo -l
以root权限执行上一条命令
sudo !!

sudoers文件配置语法

1
2
user  MACHINE=COMMANDS
用户 登录的主机=(可以变换的身份) 可以执行的命令

例子:

1
2
3
4
5
6
7
8
9
10
允许root用户执行任意路径下的任意命令 
root ALL=(ALL) ALL
允许wheel用户组中的用户执行所有命令
%wheel ALL=(ALL) ALL
允许wheel用户组中的用户在不输入该用户的密码的情况下使用所有命令
%wheel ALL=(ALL) NOPASSWD: ALL
允许support用户在EPG的机器上不输入密码的情况下使用SQUID中的命令
Cmnd_Alias SQUID = /opt/vtbin/squid_refresh, /sbin/service, /bin/rm
Host_Alias EPG = 192.168.1.1, 192.168.1.2
support EPG=(ALL) NOPASSWD: SQUID

添加、删除组账号:groupadd、groupdel

groupadd 新建组账号 groupdel 组账号 cat /etc/group 查看用户组

1
2
python@ubuntu:~/test$ sudo groupadd abc
python@ubuntu:~/test$ sudo groupdel abc

用户组管理:groupmod

修改用户组的属性使用groupmod命令。其语法如下:

1
groupmod 选项 用户组

常用的选项有:

  • -g GID 为用户组指定新的组标识号。

  • -o 与-g选项同时使用,用户组的新GID可以与系统已有用户组的GID相同。

  • -n新用户组 将用户组的名字改为新名字

将组group2的组标识号修改为102:

1
groupmod -g 102 group2

将组group2的标识号改为10000,组名修改为group3:

1
groupmod –g 10000 -n group3 group2

如果一个用户同时属于多个用户组,那么用户可以在用户组之间切换,以便具有其他用户组的权限。

用户可以在登录后,使用命令newgrp切换到其他用户组,这个命令的参数就是目的用户组。例如:

1
$ newgrp root

这条命令将当前用户切换到root用户组,前提条件是root用户组确实是该用户的主组或附加组。类似于用户账号的管理,用户组的管理也可以通过集成的系统管理工具来完成。

权限管理

列出目录的内容:ls

Linux文件或者目录名称最长可以有265个字符,“.”代表当前目录,“…”代表上一级目录,以“.”开头的文件为隐藏文件,需要用 -a 参数才能显示。

ls常用参数:

参数含义
-a显示指定目录下所有子目录与文件,包括隐藏文件
-l以列表方式显示文件的详细信息
-h配合 -l 以人性化的方式显示文件大小

image-20250218170841665

列出的信息的含义:

img

ls支持通配符:

通配符含义
*文件代表文件名中所有字符
ls te*查找以te开头的文件
ls *html查找结尾为html的文件
代表文件名中任意一个字符
ls ?.c只找第一个字符任意,后缀为.c的文件
ls a.?只找只有3个字符,前2字符为a.,最后一个字符任意的文件
[][”和“]”将字符组括起来,表示可以匹配字符组中的任意一个。“-”用于表示字符范围。
[abc]匹配a、b、c中的任意一个
[a-f]匹配从a到f范围内的的任意一个字符
ls [a-f]*找到从a到f范围内的的任意一个字符开头的文件
ls a-f查找文件名为a-f的文件,当“-”处于方括号之外失去通配符的作用
\如果要使通配符作为普通字符使用,可以在其前面加上转义字符。“?”和“*”处于方括号内时不用使用转义字符就失去通配符的作用。
ls \*a查找文件名为*a的文件

显示inode的内容:stat

1
stat [文件或目录]

查看 testfile 文件的inode内容内容,可以用以下命令:

1
2
3
4
5
6
7
8
9
10
[root@rocky8 ~]# stat anaconda-ks.cfg 
File: anaconda-ks.cfg
Size: 1256 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 201326724 Links: 1
Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:admin_home_t:s0
Access: 2025-02-18 21:18:29.137289911 +0800
Modify: 2025-02-18 21:18:29.216289006 +0800
Change: 2025-02-18 21:18:29.216289006 +0800
Birth: 2025-02-18 21:18:29.137289911 +0800

文件访问权限

用户能够控制一个给定的文件或目录的访问程度,一个文件或目录可能有读、写及执行权限:

  • 读权限(r) :对于文件,具有读取文件内容的权限;对于目录,具有浏览目录的权限。

  • 写权限(w) :对于文件,具有修改文件内容的权限;对于目录,具有删除、移动目录内文件的权限。

  • 可执行权限(x): 对于文件,具有执行文件的权限;对于目录,该用户具有进入目录的权限。

通常,Unix/Linux系统只允许文件的属主(所有者)或超级用户改变文件的读写权限。

示例:

img

第1个字母代表文件的类型:

  • “d” 代表文件夹

  • “-” 代表普通文件

  • “c” 代表硬件字符设备

  • “b” 代表硬件块设备

  • “s”表示管道文件

  • “l” 代表软链接文件。

后9个字母分别代表三组权限:文件所有者、用户组、其他用户拥有的权限。

chmod:修改文件权限

chmod 修改文件权限有两种使用格式:字母法与数字法。

字母法:chmod u/g/o/a +/-/= rwx 文件

[ u/g/o/a ]含义
uuser 表示该文件的所有者
ggroup 表示与该文件的所有者属于同一组( group )者,即用户组
oother 表示其他以外的人
aall 表示这三者皆是
[ ±= ]含义
+增加权限
-撤销权限
=设定权限
rwx含义
rread 表示可读取,对于一个目录,如果没有r权限,那么就意味着不能通过ls查看这个目录的内容。
wwrite 表示可写入,对于一个目录,如果没有w权限,那么就意味着不能在目录下创建新的文件。
xexcute 表示可执行,对于一个目录,如果没有x权限,那么就意味着不能通过cd进入这个目录。

数字法:“rwx” 这些权限也可以用数字来代替

字母说明
r读取权限,数字代号为 “4”
w写入权限,数字代号为 “2”
x执行权限,数字代号为 “1”
-不具任何权限,数字代号为 “0”

如执行:chmod u=rwx,g=rx,o=r filename 就等同于:chmod u=7,g=5,o=4 filename

chmod 751 file:

  • 文件所有者:读、写、执行权限

  • 同组用户:读、执行的权限

  • 其它用户:执行的权限

chmod 777 file:所有用户拥有读、写、执行权限

注意:如果想递归所有目录加上相同权限,需要加上参数“ -R ”。 如:chmod 777 test/ -R 递归 test 目录下所有文件加 777 权限

修改文件所有者:chown

1
2
3
4
5
6
7
[Corazon@rocky8:~]$ ll a
-rw-rw-r--. 1 Corazon Corazon 0 Feb 19 13:31 a
[Corazon@rocky8:~]$ su
Password:
[root@rocky8:Corazon]# chown Cora a
[root@rocky8:Corazon]# ll a
-rw-rw-r--. 1 Cora Corazon 0 Feb 19 13:31 a

修改文件所属组:chgrp

1
2
3
4
5
6
7
[root@rocky8:Corazon]# ll a
-rw-rw-r--. 1 Cora Corazon 0 Feb 19 13:31 a
[root@rocky8:Corazon]# ll a
-rw-rw-r--. 1 Cora Corazon 0 Feb 19 13:31 a
[root@rocky8:Corazon]# chgrp Cora a
[root@rocky8:Corazon]# ll a
-rw-rw-r--. 1 Cora Cora 0 Feb 19 13:31 a

特殊权限

linux共12位权限,除了9位基础权限还有3个特殊权限。

三种特殊的权限

SetUID(suid)

命令功能: **临时使用命令的属主权限执行该命令。**即如果文件有suid权限时,那么普通用户去执行该文件时,会以该文件的所属用户的身份去执行。

SetUID(简写suid):会在属主权限位的执行权限上写个s。 如果该属主权限位上有执行权限,则会在属主权限位的执行权限上写个s(小写); 如果该属主权限位上没有执行权限,则会在属主权限位的执行权限上写个S(大写)。

suid数字权限是4000,设置方法:

1
2
3
4
5
方式1
[root@centos7 ~]# chmod u+s filename
方式2
[root@centos7 ~]# chmod 4755 filename
1234

查看passwd命令的权限

1
2
`[root@localhost ftl]``# ll /usr/bin/passwd ` `问题: ``passwd``文件的属组是root,表示只有root用户可以访问的文件,为什么普通用户依然可以使用该命令更改自己的密码?``答案:当普通用户[omd]使用``passwd``命令的时候,系统看到``passwd``命令文件的属性有大写s后,表示这个命令的属主权限被omd用户获得,也就是omd用户获得文件``/etc/shadow``的root的rwx权限`
1

由于passwd具有s权限,普通用户使用该命令的时候,就会以该命令的属主身份root执行该命令,于是能够顺利修改普通用户不具备修改权限的/etc/shadow文件。

希望普通用户user1可以删除某个自己没有权限删除的文件的操作方法:

  • sudo给user1授权rm权限

  • rm设置suid

  • 修改被删除文件上级目录的权限

SetUID(简称suid)总结:

  1. 让普通用户对可执行的二进制文件,临时拥有二进制文件的属主权限;

  2. 如果设置的二进制文件没有执行权限,那么suid的权限显示就是S(大写字母S);

  3. 特殊权限suid仅对二进制可执行程序有效,其他文件或目录则无效。

  4. suid极其危险,如果给vim或者rm命令设置了setUID,那么任何文件都能编辑或者删除了,相当于有root权限了。

setGID(sgid)

**命令功能:**使用sgid可以使得多个用户之间共享一个目录的所有文件变得简单。当某个目录设置了sgid后,在该目录中新建的文件不在是创建该文件的默认所属组。

如果该属组权限位上有执行权限,则会在属组主权限位的执行权限上写个s(小写字母); 如果该属组权限位上没有执行权限,则会在属组主权限位的执行权限上写个S(大写字母S)。

write命令的权限:

1
2
3
[root@VM_0_9_centos ~]# ll /bin/write 
-rwxr-sr-x 1 root tty 19544 Aug 9 11:10 /bin/write
12

sgid数字权限是2000,设置方法:

1
2
3
4
5
6
7
8
方式1
[root@VM_0_9_centos ~]# chmod 2755 test/
方式2
[root@VM_0_9_centos ~]# chmod g+s test/

[root@VM_0_9_centos ~]# ll -d test/
drwxr-sr-x 2 root root 4096 Nov 22 21:02 test/
1234567

在设置SetGID的文件夹创建文件的属组是父目录的属组:

1
2
3
4
5
6
[root@VM_0_9_centos ~]# cd test/
[root@VM_0_9_centos test]# su aaa
[aaa@VM_0_9_centos test]$ touch bbb
[aaa@VM_0_9_centos test]$ ll
-rw-rw-r-- 1 aaa root 0 Nov 22 21:14 bbb
12345

sticky(sbit)粘滞位

**命令功能:**粘滞位,只对目录有效,对某目录设置粘滞位后,普通用户就算有w权限也只能删除该目录下自己建立的文件,而不能删除其他用户建立的文件。

如果该其他用户权限位上有执行权限,则会在其他用户权限位的执行权限上写个t(小写); 如果该其它用户权限位上没有执行权限,则会在其他用户权限位的执行权限上写个T(大写)。

系统中存在的/tmp目录是经典的粘滞位目录,谁都有写权限,因此安全成问题,常常是木马第一手跳板。

1
2
3
[aaa@VM_0_9_centos ~]$ ll -d /tmp/ 
drwxrwxrwt. 9 root root 4096 Nov 22 21:15 /tmp/
12

sbit数字权限是1000,设置方法:

1
2
3
4
5
6
7
8
方法1:
[root@VM_0_9_centos ~]# chmod 1755 test/
方法2:
[root@VM_0_9_centos ~]# chmod o+t test/
查看权限:
[root@VM_0_9_centos ~]# ll -d test/
drwxr-xr-t 2 root root 4096 Nov 22 21:15 test/
1234567

chattr权限

chattr概述:凌驾于r、w、x、suid、sgid之上的权限。

lsattr:查看特殊权限

1
2
3
[root@VM_0_9_centos ~]# lsattr /etc/passwd
-------------e-- /etc/passwd
12

chattr:设置特殊权限

权限说明
-i锁定文件,不能编辑,不能修改,不能删除,不能移动,可以执行
-a仅可以追加文件,不能编辑,不能删除,不能移动,可以执行

防止系统中某个关键文件被修改:

1
2
3
4
[root@VM_0_9_centos ~]# chattr +i /etc/fstab
[root@VM_0_9_centos ~]# lsattr /etc/fstab
----i--------e-- /etc/fstab
123

让某个文件只能往里面追加内容,不能删除,一些日志文件适用于这种操作:

1
2
3
4
[root@VM_0_9_centos ~]# chattr +a user_act.log
[root@VM_0_9_centos ~]# lsattr user_act.log
-----a-------e-- user_act.log
123

掩码umask

umask的作用

umask值用于设置用户在创建文件时的默认权限,当我们在系统中创建目录或文件时,目录或文件所具有的默认权限就是由umask值决定的。

对于root用户,系统默认的umask值是0022;对于普通用户,系统默认的umask值是0002。执行umask命令可以查看当前用户的umask值。

1
2
3
[root@VM_0_9_centos ~]# umask
0022
12

umask是如何改变新文件的权限

umask值一共有4组数字,其中第1组数字用于定义特殊权限,一般不予考虑,与一般权限有关的是后3组数字。

默认情况下,对于目录,用户所能拥有的最大权限是777;对于文件,用户所能拥有的最大权限是目录的最大权限去掉执行权限,即666。因为x执行权限对于目录是必须的,没有执行权限就无法进入目录,而对于文件则不必默认赋予x执行权限。

对于root用户,他的umask值是022。当root用户创建目录时,默认的权限就是用最大权限777去掉相应位置的umask值权限,即对于所有者不必去掉任何权限,对于所属组要去掉w权限,对于其他用户也要去掉w权限,所以目录的默认权限就是755;当root用户创建文件时,默认的权限则是用最大权限666去掉相应位置的umask值,即文件的默认权限是644。

通过umask命令可以修改umask值,比如将umask值设为0077。

1
2
3
4
[root@VM_0_9_centos ~]# umask 0077
[root@VM_0_9_centos ~]# umask
0077
123

永久修改umask

umask命令只能临时修改umask值,系统重启之后umask将还原成默认值。如果要永久修改umask值,可修改/etc/bashrc/etc/profile文件。

例如要将默认umask值设置为027,那么可以在文件中增加一行umask 027

本文参考:

Ubuntu软件安装与卸载

更新Ubuntu软件下载地址

开源软件镜像站 :https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/

Ubuntu 的软件源配置文件是 /etc/apt/sources.list。将系统自带的该文件做个备份,将该文件替换为下面内容,即可使用 TUNA 的软件源镜像。

ubuntu版本: 16.04 LTS

1
2
3
4
5
6
7
8
9
10
11
12
13
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse

然后

1
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup

再sudo vim /etc/apt/sources.list修改为以上内容

Ubuntu软件操作的相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo apt-get update  更新源
sudo apt-get install package 安装包
sudo apt-get remove package 删除包
sudo apt-cache search package 搜索软件包
sudo apt-cache show package 获取包的相关信息,如说明、大小、版本等
sudo apt-get install package --reinstall 重新安装包
sudo apt-get -f install 修复安装
sudo apt-get remove package --purge 删除包,包括配置文件等
sudo apt-get build-dep package 安装相关的编译环境
sudo apt-get upgrade 更新已安装的包
sudo apt-get dist-upgrade 升级系统
sudo apt-cache depends package 了解使用该包依赖那些包
sudo apt-cache rdepends package 查看该包被哪些包依赖
sudo apt-get source package 下载该包的源代码
sudo apt-get clean && sudo apt-get autoclean 清理无用的包
sudo apt-get check 检查是否有损坏的依赖

yum安装命令

yum( Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器。

基於RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载、安装。

yum提供了查找、安装、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。

更新国内yum源

网易(163)yum源是国内最好的yum源之一 ,无论是速度还是软件版本,都非常的不错。

将yum源设置为163 yum,可以提升软件包安装和更新的速度,同时避免一些常见软件版本无法找到。

首先备份/etc/yum.repos.d/CentOS-Base.repo

1
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

下载对应版本 repo 文件, 放入 /etc/yum.repos.d/

1
2
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
mv CentOS7-Base-163.repo /etc/yum.repos.d/CentOS-Base.repo

运行以下命令生成缓存

1
2
yum clean all
yum makecache

除了网易之外,国内还有其他不错的 yum 源,比如中科大和搜狐。

中科大的 yum 源,安装方法查看:https://lug.ustc.edu.cn/wiki/mirrors/help/centos

sohu 的 yum 源安装方法查看: http://mirrors.sohu.com/help/centos.html

yum常用命令

yum 语法:

1
yum [options] [command] [package ...]

选项:

  • **options:**可选,选项包括-h(帮助),-y(当安装过程提示选择全部为"yes"),-q(不显示安装的过程)等等。

  • **command:**要进行的操作。

  • **package:**操作的对象。

实例:

  • 列出所有可更新的软件清单命令:yum check-update

  • 更新所有软件命令:yum update

  • 仅安装指定的软件命令:yum install <package_name>

  • 仅更新指定的软件命令:yum update <package_name>

  • 显示包信息:yum info <package_name>

  • 列出所有可安裝的软件清单命令:yum list

  • 删除软件包命令:yum remove <package_name>

  • 查找软件包 命令:yum search <keyword>

  • 清除缓存命令:

    • yum clean packages: 清除缓存目录下的软件包
    • yum clean headers: 清除缓存目录下的 headers
    • yum clean oldheaders: 清除缓存目录下旧的 headers
    • yum clean, yum clean all (= yum clean packages; yum clean oldheaders) :清除缓存目录下的软件包及旧的headers

yum在线安装MySQL5.7

Step1: 检测系统是否自带安装mysql

1
yum list installed | grep mysql

Step2: 删除系统自带的mysql及其依赖

1
yum -y remove mysql-libs.x86_64

Step3: 给CentOS添加rpm源,并且选择较新的源

1
2
3
4
5
6
7
wget dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
yum localinstall mysql-community-release-el7-5.noarch.rpm
yum repolist all | grep mysql
yum-config-manager --disable mysql55-community
yum-config-manager --disable mysql56-community
yum-config-manager --enable mysql57-community-dmr
yum repolist enabled | grep mysql

Step4:安装mysql 服务器

1
yum install mysql-community-server

Step5: 启动mysql

1
service mysqld start

grep “password” /var/log/mysqld.log(查看临时密码)

1
2
3
SET PASSWORD = PASSWORD('your new password');
ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;
flush privileges;

默认的要求必须的设置格式:
包含数字、小写或大写字母以及特殊字符

默认的要求必须的设置格式:
包含数字、小写或大写字母以及特殊字符

如果不想复杂,可以使用以下方式

1
2
set global validate_password_policy=0;
set global validate_password_length=1;

Step6: 查看mysql是否自启动,并且设置开启自启动

1
2
# chkconfig --list | grep mysqld
# chkconfig mysqld on

Step7: mysql安全设置

1
mysql_secure_installation

rpm

RPM是Red Hat公司随Redhat Linux推出了一个软件包管理器,通过它能够更加轻松容易地实现软件的安装。

常见用法:

  • rpm -ivh <rpm包名> 安装软件

  • rpm -e <rpm包名> 卸载安装

  • rpm -qi <rpm包名> 显示软件安装信息

  • rpm -qa | grep xxx 查询软件是否安装(包括相关依赖)

  • rpm -Uvh <rpm包名> 升级一个rpm

具体参数详解:
-i, --install 安装包
-v, --verbose 列出更多详细信息,安装进度
-h, --hash 安装时列出hash标记 (与 -v连用)
-e, --erase 卸载安装包
-U, --upgrade=+ 升级包
–replacepkge 无论软件包是否已被安装,都强行安装软件包
–test 安装测试,并不实际安装
–nodeps 忽略软件包的依赖关系强行安装
–force 忽略软件包及文件的冲突
-q,–query:
-a, --all 查询/校验所有的安装包
-p, --package 查询/校验一个安装文件
-l, --list 列出安装文件
-d, --docfiles 列出所有文档文件
-f, --file 查询/校验安装包中所包含的文件

安装软件:

1
2
3
4
# rpm -hvi dejagnu-1.4.2-10.noarch.rpm 
警告:dejagnu-1.4.2-10.noarch.rpm: V3 DSA 签名:NOKEY, key ID db42a60e
准备...
########################################### [100%]

显示软件安装信息:

1
2
3
# rpm -qi dejagnu-1.4.2-10.noarch.rpm

【第1次更新 教程、类似命令关联】

安装JDK

1
2
3
4
5
6
7
8
9
10
11
1.上传jdk-7u45-linux-x64.tar.gz到Linux上
2.解压jdk到/usr/local目录
tar -zxvf jdk-7u45-linux-x64.tar.gz -C /usr/local/
3.设置环境变量,在/etc/profile文件最后追加相关内容(技巧r:!pwd)
vi /etc/profile
export JAVA_HOME=/usr/local/jdk1.7.0_45
export PATH=$PATH:$JAVA_HOME/bin
4.刷新环境变量
source /etc/profile
5.测试java命令是否可用
java -version

制作本地YUM源

上传CentOS-6.7-x86_64-bin-DVD1.iso到服务器

将CentOS-6.7-x86_64-bin-DVD1.iso镜像挂载到某个目录:

1
2
mkdir /var/iso
mount -o loop CentOS-6.7-x86_64-bin-DVD1.iso /var/iso

安装并启动Apache服务器:

1
2
yum install -y httpd
service httpd start

使用浏览器访问http://192.168.100.101(如果访问不通,检查防火墙是否开启了80端口或关闭防火墙)

将YUM源配置到httpd中:

1
2
cp -r /var/iso/ /var/www/html/CentOS-6.7
umount /var/iso

在浏览器中访问http://192.168.100.101/CentOS-6.7/

img

配置使用YUM源:

备份原有的YUM源的配置文件

1
2
cd /etc/yum.repos.d/
rename .repo .repo.bak *

修改YUM源配置文件

1
2
3
4
5
6
7
vi CentOS-Local.repo
[base]
name=CentOS-Local
baseurl=http://192.168.100.101/CentOS-6.7
gpgcheck=1
enabled=1 #很重要,1才启用
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

重建yum缓存

1
2
3
4
#清除yum缓存文件,重新新建
yum clean all && yum makecache
#列出可用的YUM源
yum repolist

rpm包生成yum源目录

如果已经下载好了rpm包,可以自行制作一个yum源(yum仓库)。将下载的rpm包上传到centos服务器上(比如/data/rpm目录下),然后进入存放rpm包的目录,执行以下命令:

1
2
# cd /data/rpm
# createrepo .

这样,rpm包存放的目录就可以作为yum源目录使用。如果提示找不到createrepo命令,可以使用yum install createrepo安装该程序。

本文参考:

Linux系统启动过程

Linux系统的启动过程可以分为5个阶段:

  • 内核的引导。

  • 运行 init。

  • 系统初始化。

  • 建立终端 。

  • 用户登录系统。


加载内核

当计算机打开电源后,首先是BIOS开机自检,按照BIOS中设置的启动设备(通常是硬盘)来启动。

操作系统接管硬件以后,首先读入 /boot 目录下的内核文件。

img

启动初始化进程init

内核文件加载以后,就开始运行第一个程序 /sbin/init,它的作用是初始化系统环境。

init程序首先是需要读取配置文件/etc/inittab。

CentOS 各版本init配置文件的位置:

  • SysV: init, CentOS 5之前, 配置文件: /etc/inittab。
  • Upstart: init,CentOS 6, 配置文件: /etc/inittab, /etc/init/*.conf。
  • Systemd: systemd, CentOS 7,配置文件: /usr/lib/systemd/system、 /etc/systemd/system。

1574411888879

由于init是第一个运行的程序,它的进程编号(pid)就是1。其他所有进程都从它衍生,都是它的子进程。

确定运行级别

许多程序需要开机启动。它们在Windows叫做"服务"(service),在Linux就叫做"守护进程"(daemon)。

init进程的一大任务,就是去运行这些开机启动的程序。

但是,不同的场合需要启动不同的程序,比如用作服务器时,需要启动Apache,用作桌面就不需要。

Linux允许为不同的场合,分配不同的开机启动程序,这就叫做"运行级别"(runlevel)。也就是说,启动时根据"运行级别",确定要运行哪些程序。

1574411922140

Linux系统有7个运行级别(runlevel):

  • 运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动

  • 运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆

  • 运行级别2:多用户状态(没有NFS)

  • 运行级别3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式

  • 运行级别4:系统未使用,保留

  • 运行级别5:X11控制台,登陆后进入图形GUI模式

  • 运行级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动

可以使用运行级别执行关机或重启:

1
2
3
init 0	关机
init 6 重启
12

加载开机启动程序

在init的配置文件中有这么一行: si::sysinit:/etc/rc.d/rc.sysinit它调用执行了/etc/rc.d/rc.sysinit,而rc.sysinit是一个bash shell的脚本,它主要是完成一些系统初始化的工作,rc.sysinit是每一个运行级别都要首先运行的重要脚本。

它主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。

1
2
l5:5:wait:/etc/rc.d/rc 5
1

这一行表示以5为参数运行/etc/rc.d/rc,/etc/rc.d/rc是一个Shell脚本,它接受5作为参数,去执行/etc/rc.d/rc5.d/目录下的所有的rc启动脚本,/etc/rc.d/rc5.d/目录中的这些启动脚本实际上都是一些连接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。

而这些rc启动脚本有着类似的用法,它们一般能接受start、stop、restart、status等参数。

/etc/rc.d/rc5.d/中的rc启动脚本通常是K或S开头的连接文件,对于以 S 开头的启动脚本,将以start参数来运行。

而如果发现存在相应的脚本也存在K打头的连接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先以stop为参数停止这些已经启动了的守护进程,然后再重新运行。

这样做是为了保证是当init改变运行级别时,所有相关的守护进程都将重启。

至于在每个运行级中将运行哪些守护进程,用户可以通过chkconfig或setup中的"System Services"来自行设定。

1574413056057

用户登录

一般来说,用户的登录方式有三种:

  • (1)命令行登录

  • (2)ssh登录

  • (3)图形界面登录

1574413193850

对于运行级别为5的图形方式用户来说,他们的登录是通过一个图形化的登录界面。登录成功后可以直接进入 KDE、Gnome 等窗口管理器。

而本文主要讲的还是文本方式登录的情况:当我们看到mingetty的登录界面时,我们就可以输入用户名和密码来登录系统了。

Linux 的账号验证程序是login,login会接收mingetty传来的用户名作为用户名参数。

然后login会对用户名进行分析:如果用户名不是root,且存在 /etc/nologin 文件,login 将输出 nologin 文件的内容,然后退出。

这通常用来系统维护时防止非root用户登录。只有/etc/securetty中登记了的终端才允许 root 用户登录,如果不存在这个文件,则root用户可以在任何终端上登录。

/etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。

图形模式与文字模式的切换方式

Linux预设提供了六个命令窗口终端机让我们来登录。

默认我们登录的就是第一个窗口,也就是tty1,这个六个窗口分别为tty1,tty2 … tty6,你可以按下Ctrl + Alt + F1 ~ F6 来切换它们。

如果你安装了图形界面,默认情况下是进入图形界面的,此时你就可以按Ctrl + Alt + F1 ~ F6来进入其中一个命令窗口界面。

当你进入命令窗口界面后再返回图形界面只要按下Ctrl + Alt + F7 就回来了。

如果你用的vmware 虚拟机,命令窗口切换的快捷键为 Alt + Space + F1~F6. 如果你在图形界面下请按Alt + Shift + Ctrl + F1~F6 切换至命令窗口。

login shell

1574413231936

shell,简单说就是命令行界面,让用户可以直接与操作系统对话。用户登录时打开的shell,就叫做login shell。

(1)命令行登录:首先读入 /etc/profile,这是对所有用户都有效的配置;然后依次寻找下面三个文件,这是针对当前用户的配置。

1
2
3
~/.bash_profile
~/.bash_login
~/.profile

需要注意的是,这三个文件只要有一个存在,就不再读入后面的文件了。比如,要是 ~/.bash_profile 存在,就不会再读入后面两个文件了。

(2)ssh登录:与第一种情况完全相同。

(3)图形界面登录:只加载 /etc/profile 和 /.profile。也就是说,/.bash_profile 不管有没有,都不会运行。

Linux关机

1
2
3
4
5
6
7
8
9
10
11
sync 将数据由内存同步到硬盘中。

shutdown 关机指令,你可以man shutdown 来看一下帮助文档。例如你可以运行如下命令关机:
shutdown –h 10 'This server will shutdown after 10 mins' 计算机将在10分钟后关机,并且显示信息在登陆用户的当前屏幕中。
shutdown –h now 立马关机
shutdown –h 20:25 系统会在今天20:25关机
shutdown –h +10 十分钟后关机
shutdown –r now 系统立马重启
shutdown –r +10 系统十分钟后重启
reboot 就是重启,等同于 shutdown –r now
halt 关闭系统,等同于shutdown –h now 和 poweroff

最后总结一下,不管是重启系统还是关闭系统,首先要运行sync命令,把内存中的数据写到磁盘中。

关机的命令有 shutdown –h now halt poweroffinit 0 , 重启系统的命令有 shutdown –r now reboot init 6

计算机启动的流程

img

boot是bootstrap(鞋带)的缩写,它来自一句谚语:

“pull oneself up by one’s bootstraps”

字面意思是"拽着鞋带把自己拉起来",这当然是不可能的事情。最早的时候,工程师们用它来比喻,计算机启动是一个很矛盾的过程:必须先运行程序,然后计算机才能启动,但是计算机不启动就无法运行程序!

早期真的是这样,必须想尽各种办法,把一小段程序装进内存,然后计算机才能正常运行。所以,工程师们把这个过程叫做"拉鞋带",久而久之就简称为boot了。

计算机的整个启动过程分成四个阶段。

第一阶段:BIOS

上个世纪70年代初,“只读内存”(read-only memory,缩写为ROM)发明,开机程序被刷入ROM芯片,计算机通电后,第一件事就是读取它。

BIOS全称是Basic Input/Output System,即基本输入输出系统,即下图芯片里的程序。

1574408997299

硬件自检

BIOS程序首先检查,计算机硬件能否满足运行的基本条件,这叫做"硬件自检"(Power-On Self-Test),缩写为POST

如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出CPU、内存、硬盘等信息。

1574409216362

启动顺序

硬件自检完成后,BIOS把控制权转交给下一阶段的启动程序。

下一阶段的启动程序根据BIOS设置项Boot Sequence(启动顺序)决定,排在前面的设备就是优先转交控制权的设备。

1574409397609

第二阶段: 主引加粗样式导记录

BIOS按照"启动顺序",把控制权转交给排在第一位的储存设备。

这时,计算机读取该设备的第一个扇区,也就是读取最前面的512个字节。如果这512个字节的最后两个字节是0x55和0xAA,表明这个设备可以用于启动;如果不是,表明设备不能用于启动,控制权于是被转交给"启动顺序"中的下一个设备。

这最前面的512个字节,就叫做"主引导记录"(Master boot record,缩写为MBR)。

主引导记录组成

主引导记录由三个部分组成:

(1) 第1-446字节:调用操作系统的机器码。

(2) 第447-510字节:分区表(Partition table),共64字节。

(3) 第511-512字节:主引导记录签名(0x55和0xAA)。

其中,第二部分"分区表"的作用,是将硬盘分成若干个区。

分区表

硬盘分区有很多好处。每个分区可以安装不同的操作系统,"主引导记录"因此必须知道将控制权转交给哪个区。

分区表的长度只有64个字节,里面又分成四项,每项16个字节。所以,一个硬盘最多只能分四个一级分区,又叫做"主分区"。

每个主分区的16个字节,由6个部分组成:

(1) 第1个字节:如果为0x80,就表示该主分区是激活分区,控制权要转交给这个分区。四个主分区里面只能有一个是激活的。

(2) 第2-4个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。

(3) 第5个字节:主分区类型

(4) 第6-8个字节:主分区最后一个扇区的物理位置。

(5) 第9-12字节:该主分区第一个扇区的逻辑地址。

(6) 第13-16字节:主分区的扇区总数。

最后的四个字节(“主分区的扇区总数”),决定了这个主分区的长度。也就是说,一个主分区的扇区总数最多不超过2的32次方。

如果每个扇区为512个字节,就意味着单个分区最大不超过2TB。再考虑到扇区的逻辑地址也是32位,所以单个硬盘可利用的空间最大也不超过2TB。如果想使用更大的硬盘,只有2个方法:一是提高每个扇区的字节数,二是增加扇区总数

第三阶段:硬盘启动

这时,计算机的控制权就要转交给硬盘的某个分区了,这里又分成三种情况。

情况A:卷引导记录

上一节提到,四个主分区里面,只有一个是激活的。计算机会读取激活分区的第一个扇区,叫做"卷引导记录"(Volume boot record,缩写为VBR)。

"卷引导记录"的主要作用是,告诉计算机,操作系统在这个分区里的位置。然后,计算机就会加载操作系统了。

情况B:扩展分区和逻辑分区

随着硬盘越来越大,四个主分区已经不够了,需要更多的分区。但是,分区表只有四项,因此规定有且仅有一个区可以被定义成"扩展分区"(Extended partition)。

所谓"扩展分区",就是指这个区里面又分成多个区。这种分区里面的分区,就叫做"逻辑分区"(logical partition)。

计算机先读取扩展分区的第一个扇区,叫做"扩展引导记录"(Extended boot record,缩写为EBR)。它里面也包含一张64字节的分区表,但是最多只有两项(也就是两个逻辑分区)。

计算机接着读取第二个逻辑分区的第一个扇区,再从里面的分区表中找到第三个逻辑分区的位置,以此类推,直到某个逻辑分区的分区表只包含它自身为止(即只有一个分区项)。因此,扩展分区可以包含无数个逻辑分区。

但是,似乎很少通过这种方式启动操作系统。如果操作系统确实安装在扩展分区,一般采用下一种方式启动。

情况C:启动管理器

在这种情况下,计算机读取"主引导记录"前面446字节的机器码之后,不再把控制权转交给某一个分区,而是运行事先安装的"启动管理器"(boot loader),由用户选择启动哪一个操作系统。

Linux环境中的启动管理器例如Grub

1574410612420

第四阶段:操作系统

控制权转交给操作系统后,操作系统的内核首先被载入内存。

以Linux系统为例,先载入/boot目录下面的kernel。内核加载成功后,第一个运行的程序是/sbin/init。它根据配置文件(Debian系统是/etc/initab)产生init进程。这是Linux启动后的第一个进程,pid进程编号为1,其他进程都是它的后代。

然后,init线程加载系统的各个模块,比如窗口程序和网络程序,直至执行/bin/login程序,跳出登录界面,等待用户输入用户名和密码。

至此,全部启动过程完成。

单用户模式修改Centos系统root密码

步骤如下:

重启linux系统

4_21

3 秒之内要按一下回车,出现如下界面

4_22

按向下方向键移动到第二行,按"e"进入编辑模式

4_23

在 第二行最后边输入 single,用空格与前面内容隔开

4_24

回车

4_25

最后按"b"启动,启动后就进入了单用户模式了

4_26

进入到单用户模式后,就可以使用passwd命令任意更改root密码了:

4_27

救援模式修改Ubuntu系统root密码

重启,按住shift键,出现如下界面,选中如下选项

img

按回车键进入如下界面,然后选中最新的recovery mode选项

img

按e进入如下界面,找到图中红色框的recovery nomodeset并将其删掉,再在这一行的后面输入

1
quiet splash rw init=/bin/bash

img

img

接着按F10或者Ctrl+x 后出现如下界面,在命令行内输入passwd后进行修改密码即可

img

修改完之后重启系统。

本文参考:

Linux命令行快捷键

  • Ctrl+c 结束正在运行的程序
  • Ctrl+d 结束输入或退出shell
  • Ctrl+s 暂停屏幕输出【锁住终端】
  • Ctrl+q 恢复屏幕输出【解锁终端】
  • Ctrl+l 清屏,【是字母L的小写】等同于Clear
  • 当前光标到行首:ctrl+a
  • 当前光标到行尾:ctrl+e
  • 删除当前光标到行首:ctrl+u
  • 删除当前光标到行尾:ctrl+k
  • Ctrl+y 在光标处粘贴剪切的内容
  • Ctrl+r 查找历史命令【输入关键字,就能调出以前执行过的命令】
  • Ctrl+t 调换光标所在处与其之前字符位置,并把光标移到下个字符
  • Ctrl+x+u 撤销操作
  • Ctrl+z 转入后台运行

Tips:

  • Linux命令格式:command [-options] [parameter1] …

  • 帮助文档help:command --helpcommand -h

  • tab键在敲命令式可以补全命令或文件名

  • 直接使用命令cd可以进入当前用户的家目录

  • 文件颜色及其含义

文件的颜色含义
蓝色目录
绿色可执行文件
红色压缩文件
浅蓝色链接文件
灰色其他文件

正则表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
规则:
. : 任意一个字符
a* : 任意多个a(零个或多个a)
a? : 零个或一个a
a+ : 一个或多个a
.* : 任意多个任意字符
\. : 转义.
\<h.*p\> :以h开头,p结尾的一个单词
o\{2\} : o重复两次

grep '^i.\{18\}n$' /usr/share/dict/words

查找不是以#开头的行
grep -v '^#' a.txt | grep -v '^$'

以h或r开头的
grep '^[hr]' /etc/passwd

不是以h和r开头的
grep '^[^hr]' /etc/passwd

不是以h到r开头的
grep '^[^h-r]' /etc/passwd

Linux的基本配置

1.修改主机名

1
2
3
vi /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=hadoop1

2.修改ip地址

1
2
3
4
5
6
7
8
9
vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.100.101
NETMASK=255.255.255.0

service network restart

3.修改ip地址和主机名的映射关系

1
2
3
4
vi /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.100.101 hadoop1

4.关闭iptables并设置其开机启动/不启动

1
2
3
service iptables stop
chkconfig iptables on
chkconfig iptables off

man手册

man是linux提供的一个手册,包含了绝大部分的命令、函数使用说明

该手册分成很多章节(section),使用man时可以指定不同的章节来浏览。

例:man ls ; man 2 printf

man中各个section意义如下:

  1. Standard commands(标准命令)

  2. System calls(系统调用,如open,write)

  3. Library functions(库函数,如printf,fopen)

  4. Special devices(设备文件的说明,/dev下各种设备)

  5. File formats(文件格式,如passwd)

  6. Games and toys(游戏和娱乐)

  7. Miscellaneous(杂项、惯例与协定等,例如Linux档案系统、网络协定、ASCII 码;environ全局变量)

  8. Administrative Commands(管理员命令,如ifconfig)

man是按照手册的章节号的顺序进行搜索的。

man设置了如下的功能键:

功能键功能
空格键显示手册页的下一屏
Enter键一次滚动手册页的一行
b回滚一屏
f前滚一屏
q退出man命令
h列出所有功能键
/word搜索word字符串

img

注意:实际上,我们不用指定第几个章节也用查看,如,man ls

history游览历史

当系统执行过一些命令后,可按上下键翻看以前的命令,history将执行过的命令列举出来

history保留了最近执行的命令记录,默认可以保留1000。历史清单从0开始编号到最大值。常见用法:

1
2
3
history N		显示最近N条命令
history -c 清除所有的历史记录
history -w xxx.txt 保存历史记录到文本xxx.txt

本文参考:

本文介绍使用chrom浏览器,在源码中copy element可以将博客复制下来,直接粘贴到自己的博客里。方便后期的更改。

  1. 首先,在自己喜欢的博客页面,点击鼠标右键,看到如下图片,点击最后一行检查

image-20250218162611570

  1. 然后,在右边的源码里边,找到"article_content"标签头,可以看到左侧部分的预览界面被选中的部分就是要复制粘贴文章(包括html部分),检查左侧被选中的部分是否是自己想要的部分.

image-20250218163315027

  1. 之后,再右键选择该标签(“article_content”),如下图,选择Copy element复制(或者Cut element 剪切)该标签下的所有元素

image-20250218163453271

  1. 新建一个 txt 文件,将后缀改为 .html ,把刚复制的 源代码 粘贴到文件中,浏览器打开后如下图,此时复制全文到markdown的软件Typora

image-20250220122601039

本文参考:

如何csdn复制他人博客文章到自己博客下

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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
1.进入到用户根目录
cd ~ 或 cd

2.查看当前所在目录
pwd

3.进入到hadoop用户根目录
cd ~hadoop

4.返回到原来目录
cd -

5.返回到上一级目录
cd ..

6.查看hadoop用户根目录下的所有文件
ls -la

7.在根目录下创建一个hadoop的文件夹
mkdir /hadoop

8.在/hadoop目录下创建src和WebRoot两个文件夹
分别创建:mkdir /hadoop/src
mkdir /hadoop/WebRoot
同时创建:mkdir /hadoop/{src,WebRoot}

进入到/hadoop目录,在该目录下创建.classpath和README文件
分别创建:touch .classpath
touch README
同时创建:touch {.classpath,README}

查看/hadoop目录下面的所有文件
ls -la

在/hadoop目录下面创建一个test.txt文件,同时写入内容"this is test"
echo "this is test" > test.txt

查看一下test.txt的内容
cat test.txt
more test.txt
less test.txt

向README文件追加写入"please read me first"
echo "please read me first" >> README

将test.txt的内容追加到README文件中
cat test.txt >> README

拷贝/hadoop目录下的所有文件到/hadoop-bak
cp -r /hadoop /hadoop-bak

进入到/hadoop-bak目录,将test.txt移动到src目录下,并修改文件名为Student.java
mv test.txt src/Student.java

在src目录下创建一个struts.xml
> struts.xml

删除所有的xml类型的文件
rm -rf *.xml

删除/hadoop-bak目录和下面的所有文件
rm -rf /hadoop-bak

返回到/hadoop目录,查看一下README文件有多单词,多少个少行
wc -w README
wc -l README

返回到根目录,将/hadoop目录先打包,再用gzip压缩
分步完成:tar -cvf hadoop.tar hadoop
gzip hadoop.tar
一步完成:tar -zcvf hadoop.tar.gz hadoop

将其解压缩,再取消打包
分步完成:gzip -d hadoop.tar.gz 或 gunzip hadoop.tar.gz
一步完成:tar -zxvf hadoop.tar.gz

将/hadoop目录先打包,同时用bzip2压缩,并保存到/tmp目录下
tar -jcvf /tmp/hadoop.tar.bz2 hadoop

将/tmp/hadoop.tar.bz2解压到/usr目录下面
tar -jxvf hadoop.tar.bz2 -C /usr/
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081

系统命令

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
46
47
48
49
50
51
52
53
54
55
1.查看主机名
hostname

2.修改主机名(重启后无效)
hostname hadoop

3.修改主机名(重启后永久生效)
vi /ect/sysconfig/network

4.修改IP(重启后无效)
ifconfig eth0 192.168.12.22

5.修改IP(重启后永久生效)
vi /etc/sysconfig/network-scripts/ifcfg-eth0

6.查看系统信息
uname -a
uname -r

7.查看ID命令
id -u
id -g

8.日期
date
date +%Y-%m-%d
date +%T
date +%Y-%m-%d" "%T

9.日历
cal 2012

10.查看文件信息
file filename

11.挂载硬盘
mount
umount
加载windows共享
mount -t cifs //192.168.1.100/tools /mnt

12.查看文件大小
du -h
du -ah

13.查看分区
df -h

14.ssh
ssh hadoop@192.168.1.1

15.关机
shutdown -h now /init 0
shutdown -r now /reboot
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354

查看版本信息

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
1、查看当前操作系统内核信息
uname -a
$ uname -a
zhang@rocky9:~$ uname -a
Linux rocky9 5.14.0-284.11.1.el9_2.x86_64 #1 SMP PREEMPT_DYNAMIC Tue May 9 17:09:15 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

2、查看当前操作系统版本信息
cat /proc/version
$ cat /proc/version
Linux version 3.10.0-693.21.1.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) ) #1 SMP Wed Mar 7 19:03:37 UTC 2018

3、查看当前操作系统发行版信息
cat /etc/issue 或 cat /etc/redhat-release
$ cat /etc/issue
\S
Kernel \r on an \m

$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

4、查看cpu相关信息,包括型号、主频、内核信息等
cat /proc/cpuinfo
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel® Xeon® CPU E5-2660 0 @ 2.20GHz
stepping : 7
microcode : 0xffffffff
cpu MHz : 2199.998
cache size : 20480 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm xsaveopt
bogomips : 4399.99
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel® Xeon® CPU E5-2660 0 @ 2.20GHz
stepping : 7
microcode : 0xffffffff
cpu MHz : 2199.998
cache size : 20480 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx hypervisor lahf_lm xsaveopt
bogomips : 4399.99
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:

5、列出所有版本信息
lsb_release -a
$ lsb_release -a
-bash: lsb_release: command not found
出现command not found说明没安装lsb_realease,可以执行命令yum install -y redhat-lsb安装lsb_realease,安装完成后,版本信息如下:
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.4.1708 (Core)
Release: 7.4.1708
Codename: Core

用户和组

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
添加一个tom用户,设置它属于users组,并添加注释信息
分步完成:useradd tom
usermod -g users tom
usermod -c "hr tom" tom
一步完成:useradd -g users -c "hr tom" tom

设置tom用户的密码
passwd tom

修改tom用户的登陆名为tomcat
usermod -l tomcat tom

将tomcat添加到sys和root组中
usermod -G sys,root tomcat

查看tomcat的组信息
groups tomcat

添加一个jerry用户并设置密码
useradd jerry
passwd jerry

添加一个名为america的组
groupadd america

jerry添加到america组中
usermod -g america jerry

将tomcat用户从root组和sys组删除
gpasswd -d tomcat root
gpasswd -d tomcat sys

将america组名修改为am
groupmod -n am america
12345678910111213141516171819202122232425262728293031323334

权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
创建a.txt和b.txt文件,将他们设为其拥有者和所在组可写入,但其他以外的人则不可写入:
chmod ug+w,o-w a.txt b.txt

创建c.txt文件所有人都可以写和执行
chmod a=wx c.txt 或chmod 666 c.txt

将/hadoop目录下的所有文件与子目录皆设为任何人可读取
chmod -R a+r /hadoop

将/hadoop目录下的所有文件与子目录的拥有者设为root,用户拥有组为users
chown -R root:users /hadoop

将当前目录下的所有文件与子目录的用户皆设为hadoop,组设为users
chown -R hadoop:users *
1234567891011121314

帮助文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1.内部命令:echo
查看内部命令帮助:help echo 或者 man echo

2.外部命令:ls
查看外部命令帮助:ls --help 或者 man ls 或者 info ls

3.man文档的类型(1~9)
man 7 man
man 5 passwd

4.快捷键:
ctrl + c:停止进程
ctrl + l:清屏
ctrl + r:搜索历史命令
ctrl + q:退出

5.善于用tab
1234567891011121314151617

文件相关命令

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
1.进入到用户根目录
cd ~ 或者 cd
cd ~hadoop
回到原来路径
cd -

2.查看文件详情
stat a.txt

3.移动
mv a.txt /ect/
改名
mv b.txt a.txt
移动并改名
mv a.txt ../b.txt

4拷贝并改名
cp a.txt /etc/b.txt

5.vi撤销修改
ctrl + u (undo)
恢复
ctrl + r (redo)

6.名令设置别名(重启后无效)
alias ll="ls -l"
取消
unalias ll

7.如果想让别名重启后仍然有效需要修改
vi ~/.bashrc

8.添加用户
useradd hadoop
passwd hadoop

9创建多个文件
touch a.txt b.txt
touch /home/{a.txt,b.txt}

10.将一个文件的内容复制到里另一个文件中
cat a.txt > b.txt
追加内容
cat a.txt >> b.txt


11.将a.txt 与b.txt设为其拥有者和其所属同一个组者可写入,但其他以外的人则不可写入:
chmod ug+w,o-w a.txt b.txt

chmod a=wx c.txt

12.将当前目录下的所有文件与子目录皆设为任何人可读取:
chmod -R a+r *

13.将a.txt的用户拥有者设为users,组的拥有者设为jessie:
chown users:jessie a.txt

14.将当前目录下的所有文件与子目录的用户的使用者为lamport,组拥有者皆设为users
chown -R lamport:users *

15.将所有的java语言程式拷贝至finished子目录中:
cp *.java finished

16.将目前目录及其子目录下所有扩展名是java的文件列出来。
find -name "*.java"
查找当前目录下扩展名是java 的文件
find -name *.java

17.删除当前目录下扩展名是java的文件
rm -f *.java
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970

VIM

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
i
a/A
o/O
r + ?替换

0:文件当前行的开头
$:文件当前行的末尾
G:文件的最后一行开头
1 + G到第一行
9 + G到第九行 = :9

dd:删除一行
3dd:删除3行
yy:复制一行
3yy:复制3行
p:粘贴
u:undo
ctrl + r:redo

"a剪切板a
"b剪切板b

"ap粘贴剪切板a的内容

每次进入vi就有行号
vi ~/.vimrc
set nu

:w a.txt另存为
:w >> a.txt内容追加到a.txt

:e!恢复到最初状态

:1,$s/hadoop/root/g 将第一行到追后一行的hadoop替换为root
:1,$s/hadoop/root/c 将第一行到追后一行的hadoop替换为root(有提示)
1234567891011121314151617181920212223242526272829303132333435

查找

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
1.查找可执行的命令:
which ls

2.查找可执行的命令和帮助的位置:
whereis ls

3.查找文件(需要更新库:updatedb)
locate hadoop.txt

4.从某个文件夹开始查找
find / -name "hadooop*"
find / -name "hadooop*" -ls

5.查找并删除
find / -name "hadooop*" -ok rm {} \;
find / -name "hadooop*" -exec rm {} \;

6.查找用户为hadoop的文件
find /usr -user hadoop -ls

7.查找用户为hadoop并且(-a)拥有组为root的文件
find /usr -user hadoop -a -group root -ls

8.查找用户为hadoop或者(-o)拥有组为root并且是文件夹类型的文件
find /usr -user hadoop -o -group root -a -type d

9.查找权限为777的文件
find / -perm -777 -type d -ls

10.显示命令历史
history

11.grep
grep hadoop /etc/password
12345678910111213141516171819202122232425262728293031323334

打包与压缩

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
1.gzip压缩
gzip a.txt

2.解压
gunzip a.txt.gz
gzip -d a.txt.gz

3.bzip2压缩
bzip2 a

4.解压
bunzip2 a.bz2
bzip2 -d a.bz2

5.将当前目录的文件打包
tar -cvf bak.tar .
将/etc/password追加文件到bak.tar中(r)
tar -rvf bak.tar /etc/password

6.解压
tar -xvf bak.tar

7.打包并压缩gzip
tar -zcvf a.tar.gz

8.解压缩
tar -zxvf a.tar.gz
解压到/usr/下
tar -zxvf a.tar.gz -C /usr

9.查看压缩包内容
tar -ztvf a.tar.gz

zip/unzip

10.打包并压缩成bz2
tar -jcvf a.tar.bz2

11.解压bz2
tar -jxvf a.tar.bz2
12345678910111213141516171819202122232425262728293031323334353637383940

输入输出重定向

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
1.新建一个文件
touch a.txt
> b.txt

2.错误重定向:2>
find /etc -name zhaoxing.txt 2> error.txt

3.将正确或错误的信息都输入到log.txt中
find /etc -name passwd > /tmp/log.txt 2>&1
find /etc -name passwd &> /tmp/log.txt

4.追加>>

5.将小写转为大写(输入重定向)
tr "a-z" "A-Z" < /etc/passwd

6.自动创建文件
cat > log.txt << EXIT
> ccc
> ddd
> EXI

7.查看/etc下的文件有多少个?
ls -l /etc/ | grep '^d' | wc -l

8.查看/etc下的文件有多少个,并将文件详情输入到result.txt中
ls -l /etc/ | grep '^d' | tee result.txt | wc -l
123456789101112131415161718192021222324252627

进程控制

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
1.查看用户最近登录情况
last
lastlog

2.查看硬盘使用情况
df

3.查看文件大小
du

4.查看内存使用情况
free

5.查看文件系统
/proc

6.查看日志
ls /var/log/

7.查看系统报错日志
tail /var/log/messages

8.查看进程
top

9.结束进程
kill 1234
kill -9 4333
12345678910111213141516171819202122232425262728

其他命令

远程文件复制:scp

scp 命令用于 Linux 之间复制文件和目录,scp是 secure copy 的缩写是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。

scp 是加密的,rcp 是不加密的,scp 是 rcp 的加强版。

使用scp命令要确保使用的用户具有可读取远程服务器相应文件的权限,否则scp命令是无法起作用的。

从本地复制到远程命令格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
复制文件
scp local_file remote_username@remote_ip:remote_folder
或者
scp local_file remote_username@remote_ip:remote_file
或者
scp local_file remote_ip:remote_folder
或者
scp local_file remote_ip:remote_file

复制文件夹
scp -r local_folder remote_username@remote_ip:remote_folder
或者
scp -r local_folder remote_ip:remote_folder
12345678910111213

实例:

1
2
3
4
5
6
7
8
scp /home/space/music/1.mp3 root@xiaoxiaoming.xyz:/home/root/others/music 
scp /home/space/music/1.mp3 root@xiaoxiaoming.xyz:/home/root/others/music/001.mp3
scp /home/space/music/1.mp3 xiaoxiaoming.xyz:/home/root/others/music
scp /home/space/music/1.mp3 xiaoxiaoming.xyz:/home/root/others/music/001.mp3

scp -r /home/space/music/ root@xiaoxiaoming.xyz:/home/root/others/
scp -r /home/space/music/ xiaoxiaoming.xyz:/home/root/others/
1234567

从远程复制到本地:

1
2
3
scp root@xiaoxiaoming.xyz:/home/root/others/music /home/space/music/1.mp3 
scp -r xiaoxiaoming.xyz:/home/root/others/ /home/space/music/
12

-P 参数来设置命令的端口号:

1
2
3
#scp 命令使用端口号 4588
scp -P 4588 remote@xiaoxiaoming.xyz:/usr/local/sin.sh /home/administrator
12

locate查找

locate命令会去保存文档和目录名称的数据库内,查找文件或目录。

一般情况我们只需要输入locate your_file_name 即可查找指定文件。

参数:

  • -d或–database= 配置locate指令使用的数据库。locate指令预设的数据库位于/var/lib/mlocate目录里,文档名为mlocate.db。

查找passwd文件,输入以下命令:

1
2
locate passwd
1

locate与find的区别: find 是去硬盘找,locate 只在/var/lib/slocate资料库中找。

locate的速度比find快,它并不是真的查找,而是查数据库,一般文件数据库在/var/lib/mlocate/mlocate.db中,所以locate的查找并不是实时的,而是以数据库的更新为准,一般是系统自己维护,也可以手工升级数据库 ,命令为:

1
2
updatedb
1

which命令

which查找$PATH中设置命令及安装文件目录所在位置

1
2
3
python@ubuntu:/var/lib/mlocate$ which locate
/usr/bin/locate
12

echo

常见用法:

1
2
3
4
5
6
7
python@ubuntu:~$ echo -e "hello\t\t world!"  解析转义字符
hello world!
python@ubuntu:~$ echo -E "hello\t\t world!" 不解析转义字符
hello\t\t world!
python@ubuntu:~$ echo $a 输出环境变量
b
123456

设置或显示环境变量:export

在 shell 中执行程序时,shell 会提供一组环境变量。export 可新增,修改或删除环境变量,供后续执行的程序使用。export 的效力仅限于该次登陆操作。

1
2
export [-fnp][变量名称]=[变量设置值]
1

参数说明

  • -f  代表[变量名称]中为函数名称。

  • -n  删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。

  • -p  列出所有的shell赋予程序的环境变量。

1
2
3
# export MYENV=7 //定义环境变量并赋值
# export -p //列出当前的环境变量
12

修改主机名&ip地址

显示主机名:hostname

临时修改:hostname xxx

永久修改

对于Ubuntu 系统

1
2
vim /etc/hostname
1

对于centos系统

1
2
vim /etc/sysconfig/network
1

在此配置文件中添加一条HOSTNAME=node1

针对centos7系统,可以使用如下命令

1
2
hostnamectl set-hostname xxx
1

一般需要重开shell甚至重启操作系统才能生效。

修改IP地址

ifconfig eth0 192.168.12.22(重启后无效)

1
2
vim /etc/sysconfig/network-scripts/ifcfg-eth0
1

mount挂载

mount 挂载外部存储设备到文件系统中

1
2
3
mkdir /mnt/cdrom 创建一个目录,用来挂载
mount -t iso9660 -o ro /dev/cdrom /mnt/cdrom/
12

将设备/dev/cdrom挂载到 挂载点 : /mnt/cdrom中

1
2
umount /mnt/cdrom
1

ssh免密登陆

假如 A 要登陆 B
在A上操作:首先生成密钥对

1
2
ssh-keygen (提示时,直接回车即可)
1

再将A自己的公钥拷贝并追加到B的授权列表文件authorized_keys中

1
2
ssh-copy-id B
1

批量添加用户

与用户账号有关的系统文件

完成用户管理的工作本质都是对有关的系统文件进行修改,这些系统文件包括/etc/passwd, /etc/shadow, /etc/group等。

/etc/passwd记录用户的基本属性

它的内容类似下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# cat /etc/passwd

root:x:0:0:Superuser:/:
daemon:x:1:1:System daemons:/etc:
bin:x:2:2:Owner of system commands:/bin:
sys:x:3:3:Owner of system files:/usr/sys:
adm:x:4:4:System accounting:/usr/adm:
uucp:x:5:5:UUCP administrator:/usr/lib/uucp:
auth:x:7:21:Authentication administrator:/tcb/files/auth:
cron:x:9:16:Cron daemon:/usr/spool/cron:
listen:x:37:4:Network daemon:/usr/net/nls:
lp:x:71:18:Printer administrator:/usr/spool/lp:
sam:x:200:50:Sam san:/home/sam:/bin/sh
12345678910111213

/etc/passwd中一行记录对应着一个用户,每行记录又被冒号(:)分隔为7个字段,其格式和具体含义如下:

1
2
用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell
1

用户名:

通常长度不超过8个字符,由大小写字母和/或数字组成,不能有冒号(😃。登录名中不能有冒号(😃,因为冒号在这里是分隔符。

为了兼容起见,登录名中最好不要包含点字符(.),并且不使用连字符(-)和加号(+)打头。

口令:

本身存放用户口令的加密串,但现在许多Linux 系统都使用了shadow技术,把真正的加密后的用户口令字存放到/etc/shadow文件中,而/etc/passwd文件的口令字段中只存放一个特殊的字符,例如“x”或者“*”。

用户标识号:

是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的,如果几个用户名对应的用户标识号是一样的,系统内部将把它们视为同一个用户,但是它们可以有不同的口令、不同的主目录以及不同的登录Shell等。

通常用户标识号的取值范围是0~65 535。0是超级用户root的标识号,1~99由系统保留,作为管理账号,普通用户的标识号从100开始。

组标识号:

记录用户所属的用户组,对应着/etc/group文件中的一条记录。

注释性描述:

一段任意编写的注释,创建账户时可以通过useradd -c 用户名-c参数指定。

主目录:

用户的起始工作目录,用户在登录到系统之后所处的目录。

登录Shell:

用户登录后,要启动一个进程,负责将用户的操作传给内核,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即Shell。

Shell是用户与Linux系统之间的接口。Linux的Shell有许多种,每种都有不同的特点。常用的有sh(Bourne Shell), csh(C Shell), ksh(Korn Shell), tcsh(TENEX/TOPS-20 type C Shell), bash(Bourne Again Shell)等。

可以通过usermod的-s参数为用户指定某个Shell。如果useradd不通过-s参数指定shell,那么系统使用bash为默认的登录Shell,即这个字段的值为/bin/bash。

为用户的登录指定特定的Shell可以限制用户只能运行指定的应用程序,在该应用程序运行结束后,用户就自动退出了系统。不过大部分Linux系统要求只有在系统中登记过的shell才能出现在这个字段中。

伪用户(pseudo users)

这些用户的登陆shell为/usr/sbin/nologin,即不能登录。它们的存在主要是方便系统管理,满足相应的系统进程对文件属主的要求。

常见的伪用户如下所示:

1
2
3
4
5
6
7
bin 拥有可执行的用户命令文件 
sys 拥有系统文件
adm 拥有帐户文件
uucp UUCP使用
lp lp或lpd子系统使用
nobody NFS使用
123456

还有许多标准的伪用户,例如:audit, cron, mail, usenet等,它们也都各自为相关的进程和文件所需要。

/etc/shadow

对安全性要求较高的Linux系统都把/etc/passwd文件中的口令字段保存在/etc/shadow文件中,超级用户才拥有该文件读权限。

/etc/shadow中的记录行与/etc/passwd中的一一对应,它由pwconv命令根据/etc/passwd中的数据自动产生

字段是:

1
2
登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志
1
  1. "登录名"是与/etc/passwd文件中的登录名相一致的用户账号

  2. "口令"字段存放的是加密后的用户口令字,长度为13个字符。如果为空,则对应用户没有口令,登录时不需要口令;如果含有不属于集合 { ./0-9A-Za-z }中的字符,则对应的用户不能登录。

  3. "最后一次修改时间"表示的是从某个时刻起,到用户最后一次修改口令时的天数。大部分linux系统的时间起点是1970年1月1日。

  4. "最小时间间隔"指的是两次修改口令之间所需的最小天数。

  5. "最大时间间隔"指的是口令保持有效的最大天数。

  6. "警告时间"字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。

  7. "不活动时间"表示的是用户没有登录活动但账号仍能保持有效的最大天数。

  8. "失效时间"字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了。

下面是/etc/shadow的一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# cat /etc/shadow

root:Dnakfw28zf38w:8764:0:168:7:::
daemon:*::0:0::::
bin:*::0:0::::
sys:*::0:0::::
adm:*::0:0::::
uucp:*::0:0::::
nuucp:*::0:0::::
auth:*::0:0::::
cron:*::0:0::::
listen:*::0:0::::
lp:*::0:0::::
sam:EkdiSECLWPdSa:9740:0:0::::
1234567891011121314

/etc/group记录用户组信息

每个用户都属于某个用户组;一个组中可以有多个用户,一个用户也可以属于不同的组。

当一个用户同时是多个组中的成员时,在/etc/passwd文件中记录的是用户所属的主组,也就是登录时所属的默认组,而其他组称为附加组。

用户要访问属于附加组的文件时,必须首先使用newgrp命令使自己成为所要访问的组中的成员。

用户组的所有信息都存放在/etc/group文件中,字段有:

1
2
组名:口令:组标识号:组内用户列表
1
  1. "组名"是用户组的名称,由字母或数字构成。与/etc/passwd中的登录名一样,组名不应重复。

  2. "口令"字段存放的是用户组加密后的口令字。一般Linux 系统的用户组都没有口令,即这个字段一般为空,或者是*。

  3. "组标识号"与用户标识号类似,也是一个整数,被系统内部用来标识组。

  4. "组内用户列表"是属于这个组的所有用户的列表,不同用户之间用逗号(,)分隔。这个用户组可能是用户的主组,也可能是附加组。

/etc/group文件的一个例子如下:

1
2
3
4
5
6
7
8
root::0:root
bin::2:root,bin
sys::3:root,uucp
adm::4:root,adm
daemon::5:root,daemon
lp::7:root,lp
users::20:root,sam
1234567

实操

先编辑一个文本用户文件

每一列按照/etc/passwd密码文件的格式书写,要注意每个用户的用户名、UID、宿主目录都不可以相同,其中密码栏可以留做空白或输入x号。一个范例文件user.txt内容如下:

1
2
3
4
5
6
7
user001::601:100:user:/home/user001:/bin/bash
user002::602:100:user:/home/user002:/bin/bash
user003::603:100:user:/home/user003:/bin/bash
user004::604:100:user:/home/user004:/bin/bash
user005::605:100:user:/home/user005:/bin/bash
user006::606:100:user:/home/user006:/bin/bash
123456

执行/usr/sbin/newusers命令

需要root权限:

1
2
# newusers < user.txt
1

可以执行命令 vipwvi /etc/passwd 检查 /etc/passwd 文件是否已经出现这些用户的数据,并且用户的宿主目录是否已经创建。

取消 shadow password 功能

/etc/shadow 产生的 shadow 密码解码,然后回写到 /etc/passwd 中,并将/etc/shadowshadow密码栏删掉。这是为了方便下一步的密码转换工作,即先取消 shadow password 功能。

执行/usr/sbin/pwunconv命令:

1
2
# pwunconv
1

编辑每个用户的密码对照文件

格式为:

1
2
用户名:密码
1

实例文件 passwd.txt 内容如下:

1
2
3
4
5
6
7
user001:123456
user002:123456
user003:123456
user004:123456
user005:123456
user006:123456
123456

执行 /usr/sbin/chpasswd命令

需要root权限:

创建用户密码,chpasswd 会将经过 /usr/bin/passwd 命令编码过的密码写入 /etc/passwd 的密码栏。

1
2
# chpasswd < passwd.txt
1

将密码编码为 shadow password

执行命令 /usr/sbin/pwconv 将密码编码为 shadow password,并将结果写入 /etc/shadow

1
2
# pwconv
1

这样就完成了大量用户的创建了,之后您可以到/home下检查这些用户宿主目录的权限设置是否都正确,并登录验证用户密码是否正确。

完整步骤

先准备好用户文件user和密码文件passwd

然后运行:

1
2
3
4
5
newusers < user
pwunconv
chpasswd < passwd
pwconv
1234

crontab的使用

crontab命令是cron table的简写,它是cron的配置文件,也可以叫它作业列表。

相关配置文件如下:

  • /var/spool/cron/ 目录下存放的是每个用户包括root的crontab任务,每个任务以创建者的名字命名

  • /etc/crontab 这个文件负责调度各种管理和维护任务。

  • /etc/cron.d/ 这个目录用来存放任何要执行的crontab文件或脚本。

  • 还可以把脚本放在/etc/cron.hourly、/etc/cron.daily、/etc/cron.weekly、/etc/cron.monthly目录中,让它每小时/天/星期、月执行一次。

命令格式:

1
2
3
4
5
6
crontab [ -u user ] { -l | -r | -e }
//省略用户表表示操作当前用户的crontab
-e (编辑工作表)
-l (列出工作表里的命令)
-r (删除工作表)
12345

crontab -e进入当前用户的工作表编辑,是常见的vim界面。每行是一条命令。

crontab的命令构成为 时间+动作,其时间有分、时、日、月、周五种,操作符有

  • ***** 取值范围内的所有数字

  • / 每过多少个数字

  • - 从X到Z

  • **,**散列数字

基本格式 :

1
2
3
4
5
6
7
8
9
f1	f2	f3	f4	f5	command
分 时 日 月 周 命令
1列表示分钟059 每分钟用*或者 */1表示
2列表示小时0230表示0点)
3列表示日期131
4列表示月份112
5列标识号星期060表示星期天)
6列要运行的命令
12345678

img

  • 其中 f1 是表示分钟,f2 表示小时,f3 表示一个月份中的第几日,f4 表示月份,f5 表示一个星期中的第几天。command表示要执行的命令。

  • 当 f1 为 * 时表示每分钟都要执行 program,f2 为 * 时表示每小时都要执行程序,以此类推

  • 当 f1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行,f2 为 a-b 时表示从第 a 到第 b 小时都要执行,以此类推

  • 当 f1 为 */n 时表示每 n 分钟个时间间隔执行一次,f2 为 */n 表示每 n 小时个时间间隔执行一次,以此类推

  • 当 f1 为 a, b, c,… 时表示第 a, b, c,… 分钟要执行,f2 为 a, b, c,… 时表示第 a, b, c…个小时要执行,以此类推

在 12 月内, 每天的早上 6 点到 12 点,每隔 3 个小时 0 分钟执行一次 /usr/bin/backup

1
2
0 6-12/3 * 12 * /usr/bin/backup
1

周一到周五每天下午 5:00 寄一封信给 alex@domain.name

1
2
0 17 * * 1-5 mail -s "hi" alex@domain.name < /tmp/maildata
1

每月每天的午夜 0 点 20 分, 2 点 20 分, 4 点 20 分…执行 echo “haha”

1
2
20 0-23/2 * * * echo "haha"
1

示例1:

1
2
3
4
5
6
7
8
9
10
11
12
45 4 1,10,22 * * /etc/init.d/smb restart 每月11022日的4 : 45重启smb

10 1 * * 6,0 /etc/init.d/smb restart 每周六周日的1 : 10重启smb

0,30 18-23 * * * /etc/init.d/smb restart 每天18 : 0023 : 00之间每隔30分钟重启smb

0 23 * * 6 /etc/init.d/smb restart 每星期六的晚上11 : 00 pm重启smb

* */1 * * * /etc/init.d/smb restart 每一小时重启smb

* 23-7/1 * * * /etc/init.d/smb restart 晚上11点到早上7点之间,每隔一小时重启smb
1234567891011

示例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
0 */2 * * * /sbin/service httpd restart  每两个小时重启一次apache 

50 7 * * * /sbin/service sshd start 每天750开启ssh服务

50 22 * * * /sbin/service sshd stop 每天2250关闭ssh服务

0 0 1,15 * * fsck /home 每月1号和15号检查/home 磁盘

1 * * * * /home/bruce/backup 每小时的第一分执行 /home/bruce/backup这个文件

00 03 * * 1-5 find /home "*.xxx" -mtime +4 -exec rm {} \; 每周一至周五3点钟,在目录/home中,查找文件名为*.xxx的文件,并删除4天前的文件。

30 6 */10 * * ls 每月的1112131日是的630执行一次ls命令
12345678910111213

环境变量问题:

有时创建了一个crontab,但是这个任务却无法自动执行,而手动执行这个任务却没有问题,这种情况一般是由于在crontab文件中没有配置环境变量引起的。

所以注意如下3点:

1)脚本中涉及文件路径时写全局路径;

2)脚本执行要用到java或其他环境变量时,通过source命令引入环境变量,如:

1
2
3
4
5
6
cat start_cbp.sh
#!/bin/sh
source /etc/profile
export RUN_CONF=/home/d139/conf/platform/cbp/cbp_jboss.conf
/usr/local/jboss-4.0.5/bin/run.sh -c mev &
12345

3)当手动执行脚本OK,但是crontab死活不执行时,可以尝试在crontab中直接引入环境变量解决问题。如:

1
2
0 * * * * . /etc/profile;/bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh
1

虚拟机

三种网络模式

桥接

在网络网卡上安装了一个桥接协议,让这块网卡处于混杂模式,可以同时连接多个网络的做法。

桥接下,类似于把物理主机虚拟为一个交换机,所有桥接设置的虚拟机连接到这个交换机的一个接口上,物理主机也同样查在这个交换机当中,所以所有桥接下网卡与网卡都是交换模式的,相互可以访问而不干扰。

img

Host-only(仅与主机通信)

虚拟机使用VMnet1网卡与主机单独组网,主机对于虚拟机相当于路由器

img

NAT

虚拟机使用VMnet8网卡与主机单独组网,主机对于虚拟机相当于路由器,VMnet8网卡通过NAT地址转换协议与物理机网卡通信

img

img

常见问题

修改静态地址后发现无法ping外网

1
2
3
4
5
6
需要设置网关
route add default gw 192.168.33.1
添加nameserver
vi /etc/resolv.conf
nameserver 192.168.33.1
12345

虚拟机克隆后eth0消失

1
2
3
4
5
6
7
直接修改  /etc/sysconfig/network-script/ifcfg-eth0
删掉UUID HWADDR
配置静态地址
然后:
rm -rf  /etc/udev/rules.d/70-persistent-net.rules
然后 reboot
123456

Hexo 默认搭配的 Markdown 渲染器是 hexo-renderer-marked,但其支持的渲染格式有限,不利于自由写作。因此,今天教大家如何更换为功能更加强大,渲染速度更快的 hexo-renderer-markdown-it 渲染器,并且还会详细介绍常用插件的配置,实现更优雅的 Markdown 写作。

container和footnote不知道为什么不能使用,估计也用不上,暂时不处理了。原文在参考文章里。

安装

卸载 hexo-renderer-marked

1
npm un hexo-renderer-marked --save

安装 hexo-renderer-markdown-it

1
npm i hexo-renderer-markdown-it --save

配置

将如下文本复制粘贴到 Hexo 的配置文件 _config.yml 的尾部

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
markdown:
preset: "default"
render:
html: true
xhtmlOut: false
langPrefix: "language-"
breaks: true
linkify: true
typographer: true
quotes: "“”‘’"
enable_rules:
disable_rules:
plugins:
- markdown-it-abbr
- markdown-it-cjk-breaks
- markdown-it-deflist
- markdown-it-emoji
- markdown-it-footnote
- markdown-it-ins
- markdown-it-mark
- markdown-it-sub
- markdown-it-sup
- markdown-it-checkbox
- markdown-it-imsize
- markdown-it-expandable
- name: markdown-it-container
options: success
- name: markdown-it-container
options: tips
- name: markdown-it-container
options: warning
- name: markdown-it-container
options: danger
anchors:
level: 2
collisionSuffix: ""
permalink: false
permalinkClass: "header-anchor"
permalinkSide: "left"
permalinkSymbol: "¶"
case: 0
separator: "-"

插件

本章节讲述各种插件的用法、配置和注意事项。

安装

分别使用 npm 命令安装以下三个插件:

1
2
3
npm i markdown-it-checkbox
npm i markdown-it-imsize
npm i markdown-it-expandable

其它插件 hexo-renderer-markdown-it 渲染器自带的有,不要安装。

用法

基础

名称描述语法示例
markdown-it-abbr注释*[HTML]: 超文本标记语言*[HTML]: 超文本标记语言
markdown-it-emoji表情:) :crab: :horse:😃 🦀 🐴
markdown-it-footnote脚注参考文献<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>参考文献1
markdown-it-ins下划线++下划线++下划线
markdown-it-mark突出显示==标记==标记
markdown-it-sub下标H~2~OH2O
markdown-it-sup上标X^2^X2
markdown-it-checkbox复选框未选
选中
image-20241111151833850

进阶

markdown-it-imsize:自定义图片宽高。

语法:(注意=100x200 前面有一个空格)

1
![test](006.png =100x200)

test

markdown-it-expandable:折叠/展开内容。

语法:

1
2
3
+++ **点击折叠**
这是被隐藏的内容
+++

效果:

 点击折叠

这是被隐藏的内容

markdown-it-container:自定义容器。

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
::: tips
**提示**
这是一个提示
:::

::: warning
**注意**
这是一个警告
:::

::: danger
**警告**
这是一个危险信号
:::

::: success
**成功**
这是一个成功信号
:::

效果:

提示
这是一个提示

注意
这是一个警告

警告
这是一个危险信号

成功
这是一个成功信号

本文参考:

【Hexo】选择更高级的Markdown渲染器