当前位置 : 首页 » 文章分类 :  开发  »  Linux-常用命令

Linux-常用命令

常用 Linux 命令笔记

鳥哥的 Linux 私房菜
http://linux.vbird.org/
http://cn.linux.vbird.org/

鸟哥的Linux私房菜:基础学习篇 第四版
https://wizardforcel.gitbooks.io/vbird-linux-basic-4e/content/

Linux命令大全
http://man.linuxde.net/

Linux命令 - 小弟调调
https://wangchujiang.com/linux-command/
jaywcjlove/linux-command
https://github.com/jaywcjlove/linux-command

Linux命令大全(手册)
https://ipcmen.com/

Linux 命令大全
http://www.runoob.com/linux/linux-command-manual.html


性能监测与优化

top

top命令可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具。

选项
-b:以批处理模式操作;
-d:屏幕刷新间隔时间;
-I:忽略失效过程;
-s:保密模式;
-S:累积模式;
-i<时间>:设置间隔时间;
-u<用户名>:指定用户名;
-p<进程号> 只查看指定的进程号,例如 -pN1 -pN2-pN1,N2,N3
-n<次数>:循环显示的次数。
-H 显示线程

交互命令

在 top 命令执行过程中可以使用的一些交互命令:
h:显示帮助画面,给出一些简短的命令总结说明;
k:终止一个进程;
i:忽略闲置和僵死进程,这是一个开关式命令;
q:退出程序;
r:重新安排一个进程的优先级别;
S:切换到累计模式;
s:改变两次刷新之间的延迟时间(单位为s),如果有小数,就换算成ms。输入0值则系统将不断刷新,默认值是5s;
f或者F:从当前显示中添加或者删除项目;
o或者O:改变显示项目的顺序;
l:切换显示平均负载和启动时间信息;
t:切换显示进程和CPU状态信息;
T:根据时间/累计时间进行排序;
w:将当前设置写入~/.toprc文件中。

z 切换彩色,即打开或关闭彩色显示
x 打开/关闭排序列的加亮效果。按一下x,排序列会高亮显示。

H 大写H,切换为线程模式

c 切换显示完整的命令行;

M 大写M,根据驻留内存大小进行排序;
P 大写P,根据CPU使用百分比大小进行排序;

e 小写 e 切换top的内存显示单位,每次切换转换率为1000,默认是 KB,切换的单位为 k,m,g,t,p。比如 top 后按一次 e 改为 MB,再按一次 e 改为 GB
m 小写 m 切换内存信息的显示形式,可以按进度条显示内存使用情况
例如按一下 m 显示为

KiB Mem : 26.6/26385116+[||||||||||||||||||||||||||                                                                          ]
KiB Swap: 61.2/4001788  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||                                       ]

再按一次 m 显示为

KiB Mem : 26.6/26385116+[                                                                                                    ]
KiB Swap: 61.2/4001788  [                                                                                                    ]

再按一次 m 不显示内存信息
再按一次 m 切换为默认形式。

top zxmc

常用组合 top 命令打开进行列表后,再按 zxmc z彩色,x排序列高亮,m进度条显示内存占用,c显示完整命令

VIRT虚拟内存/RES常驻内存

VIRT virtual memory usage 虚拟内存。
进程需要的虚拟内存总量,单位kb。包括进程使用的库、代码、数据等。
VIRT=SWAP+RES

RES resident memory usage 常驻内存。
进程当前使用的、未被换出的物理内存大小,单位kb。不包括swap out。
RES=CODE+DATA

SHR shared memory 共享内存。共享内存大小,单位kb

VSZ虚拟内存/RSS常驻内存

VSZ Virtual Memory Size 虚拟内存大小
VSZ 包括进程可以访问的所有内存,包括被换出到交换分区的内存,被分配但是还没有被使用的内存,以及动态库中的内存。
VSZ 就相当于 top 中的 VIRT

RSS Resident Set Size,常驻内存集,即进程实际占用的物理内存大小
RSS 不包括进入交换分区的内存。
RSS 包括共享库占用的内存(只要共享库在内存中)
RSS 包括所有分配的栈内存和堆内存。
RSS 就相当于 top 中的 RES

ps -p pid -o vsz,rss 查看指定 pid 的虚拟内存 vsz 大小(单位kb)和常驻内存 rss 大小(单位kb)

# ps -p 31763 -o vsz,rss
   VSZ   RSS
88459644 15892720

top结果中load过高可能原因?

top命令中load average显示的是最近1分钟、5分钟和15分钟的系统平均负载。

系统平均负载被定义为在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少进程)的平均进程数。

cpu load过高问题排查
https://www.cnblogs.com/lddbupt/p/5779655.html

top -Hp pid 查看进程的线程信息

1、top 命令加 -H 选项可以实时显示各个线程情况。
在 top 运行时,你也可以通过按 大写H 键将线程查看模式切换为开或关。

top -Hp pid 查看指定进程的线程信息,此时 PID 是线程id,开始后也可以通过 M P 来排序,找到最耗 CPU、内存的线程

# top -Hp 38532
top - 12:39:18 up 38 days, 18:37,  3 users,  load average: 131.57, 332.16, 363.02
Threads: 2288 total,   1 running, 2287 sleeping,   0 stopped,   0 zombie
%Cpu(s): 41.3 us, 12.8 sy,  0.0 ni, 45.5 id,  0.0 wa,  0.0 hi,  0.4 si,  0.0 st
KiB Mem : 26377344+total, 74095512 free, 16852987+used, 21148060 buff/cache
KiB Swap:        0 total,        0 free,        0 used. 88067968 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
58670 root      20   0 56.743g 4.874g  26472 S  3.0  1.9   0:01.10 java
47949 root      20   0 56.743g 4.874g  26472 S  2.6  1.9   0:12.51 java
33304 root      20   0 56.743g 4.874g  26472 S  2.6  1.9   0:00.13 java

2、ps 命令加 -T 选项可以开启线程查看。
“SID”栏表示线程ID,而“CMD”栏则显示了线程名称。

mac中的top命令

mac中与linux不同,top运行时,输入 ? 显示帮助
排序:
先按 o 会显示

primary key [-pid]:

其中方括号中的 -pid 表示当前是按pid排序的,之后输入cpu就是按cpu排序,输入mem就是按内存占用大小排序

实例解析

top - 18:05:51 up 35 days,  5:50,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:  93 total,   2 running,  67 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.3%st
Mem:    493420k total,   390564k used,   102856k free,    30892k buffers
Swap:  1048572k total,   611440k used,   437132k free,   101452k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
13920 root      20   0 2164m 163m 7632 S  0.3 33.9 101:01.82 java
 2836 mysql     20   0 1161m  16m 2404 S  0.0  3.4  12:49.36 mysqld
 2261 root      20   0  223m  10m 7832 S  0.0  2.1   0:36.15 amazon-ssm-agen
25137 ec2-user  20   0  856m 9004 5864 S  0.0  1.8   0:00.36 node
 4034 root      20   0  117m 7192 6116 S  0.0  1.5   0:00.01 sshd
 2300 root      20   0  242m 4560 1160 S  0.0  0.9   0:51.93 rsyslogd
 4036 ec2-user  20   0  117m 4028 2952 S  0.0  0.8   0:00.00 sshd
 4030 ec2-user  20   0 14940 3744 3396 S  0.0  0.8   0:00.00 imap
 4029 ec2-user  20   0 14912 3612 3296 S  0.0  0.7   0:00.00 imap
 4025 dovecot   20   0 32040 3596 3128 S  0.0  0.7   0:00.00 auth
 4037 ec2-user  20   0  112m 3508 3064 S  0.0  0.7   0:00.00 bash
 4024 root      20   0 12344 3172 2248 S  0.0  0.6   0:00.00 config
 2911 root      20   0 89616 2256 1812 S  0.0  0.5   2:58.89 sendmail

前五行是当前系统情况整体的统计信息区。

  • 第一行,任务队列信息,同 uptime 命令的执行结果,具体参数说明情况如下:
    14:06:23 — 当前系统时间
    up 70 days, 16:44 — 系统已经运行了70天16小时44分钟
    2 users — 当前有2个用户登录系统
    load average: 1.15, 1.42, 1.44 — load average后面的三个数分别是1分钟、5分钟、15分钟的负载情况。
    load average数据是每隔5秒钟检查一次活跃的进程数,然后按特定算法计算出的数值。如果这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了。Tasks:

  • 第二行,Tasks — 任务(进程),具体信息说明如下:
    145 total[总进程数],
    2 running[正在运行的进程数],
    143 sleeping[睡眠的进程数],
    0 stopped[停止的进程数],
    0 zombie[冻结进程数],
    系统现在共有206个进程,其中处于运行中的有1个,205个在休眠(sleep),stoped状态的有0个,zombie状态(僵尸)的有0个。

  • 第三行,cpu状态信息,具体属性说明如下:
    Cpu(s)

5.9% us — 用户空间占用CPU的百分比。
3.4% sy — 内核空间占用CPU的百分比。
0.0% ni — 用户进程空间内改变过优先级的进程占用CPU的百分比
90.4% id — 空闲CPU百分比
0.0% wa — IO等待占用CPU的百分比
0.0% hi — 硬中断(Hardware IRQ)占用CPU的百分比
0.2% si — 软中断(Software Interrupts)占用CPU的百分比
0.0 st 虚拟机(虚拟化技术)占用百分比

  • 第四行,内存状态,具体信息如下:
    Mem:
    32949016k total — 物理内存总量(32GB)
    14411180k used — 使用中的内存总量(14GB)
    18537836k free — 空闲内存总量(18GB)
    169884k buffers — 用作内核缓存的内存量 (169M)

  • 第五行,swap交换分区信息,具体信息说明如下:
    Swap:
    32764556k total — 交换区总量(32GB)
    0k used — 使用的交换区总量(0K)
    32764556k free — 空闲交换区总量(32GB)
    3612636k cached — 缓冲的交换区总量(3.6GB)

  • 第七行以下:各进程(任务)的状态监控,项目列信息说明如下:
    PID — 进程id
    USER — 进程所有者
    PR — 进程优先级
    NI — nice值。负值表示高优先级,正值表示低优先级
    VIRT virtual memory usage 虚拟内存。进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES。包括进程使用的库、代码、数据等
    RES resident memory usage 常驻内存。进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA。不包括swap out。
    SHR shared memory 共享内存。共享内存大小,单位kb
    S — 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
    %CPU — 上次更新到现在的CPU时间占用百分比
    %MEM — 进程使用的物理内存百分比
    TIME+ — 进程使用的CPU时间总计,单位1/100秒
    COMMAND — 进程名称(命令名/命令行)


uptime

uptime 命令能够打印系统总共运行了多长时间和系统的平均负载。
uptime 命令可以显示的信息显示依次为:当前时间、系统已经运行了多长时间、目前有多少用户登录到系统(连接数)、系统在过去的1分钟、5分钟和15分钟内的平均负载。

# uptime
 16:40:45 up 124 days,  1:54,  2 user,  load average: 13.01, 14.05, 14.34

注意:这里的 user 数其实是连接数,比如两个 session 用同一个用户登录,则 user 数是 2


vmstat

vmstat [options] [delay [count]]

常用方式
vmstat 2 10 第二个参数表示delay,即采样间隔单位是秒,第三个参数是count,即总的采样数。
vmstat 2 如果没有第三个参数,表示2秒采一次样,无限循环。

vmstat 命令的含义为显示虚拟内存状态(Virtual Memory Statistics),但是它可以报告关于进程、内存、I/O等系统整体运行状态。
-a:显示活动内页;
-f:显示启动后创建的进程总数;
-m:显示slab信息;
-n:头信息仅显示一次;
-s:以表格方式显示事件计数器和内存状态;
-d:报告磁盘状态;
-p:显示指定的硬盘分区状态;
-S:输出信息的单位。

$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 227676 287872      0 1419488   0    0    50    46    1    1  2  1 97  0  0

Procs(进程)
r: 运行队列中进程数量,这个值也可以判断是否需要增加CPU。(长期大于1)
b: 等待IO的进程数量。

Memory(内存)
swpd: 使用虚拟内存大小,如果swpd的值不为0,但是SI,SO的值长期为0,这种情况不会影响系统性能。
free: 空闲物理内存大小,单位 kb
buff: 用作缓冲的内存大小,单位 kb
cache: 用作缓存的内存大小,单位 kb,如果cache的值大的时候,说明cache处的文件数多,如果频繁访问到的文件都能被cache处,那么磁盘的读IO bi会非常小。

Swap
si: 每秒从磁盘交换区读入内存的大小,由磁盘调入内存。
so: 每秒写入磁盘交换区的内存大小,由内存调入磁盘。
注意:内存够用的时候,这2个值都是0,如果这2个值长期大于0时,频繁换入换出,系统性能会受到影响,磁盘IO和CPU资源都会被消耗。有些朋友看到空闲内存(free)很少的或接近于0时,就认为内存不够用了,不能光看这一点,还要结合si和so,如果free很少,但是si和so也很少(大多时候是0),那么不用担心,系统性能这时不会受到影响的。

IO(现在的Linux版本块的大小为1kb)
bi: 每秒读取的块数
bo: 每秒写入的块数
注意:随机磁盘读写的时候,这2个值越大(如超出1024k),能看到CPU在IO等待的值也会越大。

system(系统)
in: 每秒中断数,包括时钟中断。
cs: 每秒上下文切换数。例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目。例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。

注意:上面2个值越大,会看到由内核消耗的CPU时间会越大。

CPU(以百分比表示)
us: 用户进程执行时间百分比(user time)
us的值比较高时,说明用户进程消耗的CPU时间多,但是如果长期超50%的使用,那么我们就该考虑优化程序算法或者进行加速。

sy: 内核系统进程执行时间百分比(system time)
sy的值高时,说明系统内核消耗的CPU资源多,这并不是良性表现,我们应该检查原因。

wa: IO等待时间百分比
wa的值高时,说明IO等待比较严重,这可能由于磁盘大量作随机访问造成,也有可能磁盘出现瓶颈(块操作)。

id: 空闲时间百分比


iostat

iostat 主要用于监控系统设备的 IO 负载情况,iostat 首次运行时显示自系统启动开始的各项统计信息,之后运行 iostat 将显示自上次运行该命令以后的统计信息。用户可以通过指定统计的次数和时间来获得所需的统计信息。

-C 显示CPU使用情况
-d 显示磁盘使用情况
-k 以 KB 为单位显示
-m 以 M 为单位显示
-x 显示详细信息,能显示 %util
-N 显示磁盘阵列(LVM) 信息
-n 显示NFS 使用情况
-p[磁盘] 显示磁盘和分区的情况
-t 显示终端和CPU的信息
-V 显示版本信息

常用格式
iostat -dkx 2 1 -d 表示显示设备(磁盘)使用状态;-k 表示以 KB 为单位;2 表示每隔2秒刷新一次。1 表示采样1次,如果没有这个参数表示无限循环采样。
iostat -dkx 2 2秒采样一次,kb单位,无限循环
iostat -dmx 2 2秒一次采样,mb单位,无限循环
iostat -dmx /dev/sdb1 2 查看 /dev/sdb1 磁盘使用状况,MB单位,2秒1次,无限循环
iostat -dmx 2 nvme0n1 查看 nvme0n1 磁盘使用情况

# iostat -dkx 2
Linux 4.17.11-1.el7.elrepo.x86_64 (linode)     01/13/2021     _x86_64_    (24 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     1.67    0.73   72.70     7.12   731.72    20.13     0.18    2.49    0.37    2.52   0.09   0.69
sdb               0.00     8.24    0.02    5.93     0.14   102.68    34.55     0.08   13.03    7.13   13.04   5.25   3.12
dm-0              0.00     0.00    0.01   15.81     0.20   109.34    13.84     0.01    0.65    1.55    0.65   0.10   0.16
dm-1              0.00     0.00    0.00    0.00     0.00     0.00    37.79     0.00    0.42    0.42    0.00   0.25   0.00
dm-2              0.00     0.00    0.71   58.47     6.91   622.39    21.27     0.17    2.95    0.35    2.98   0.10   0.59

返回列含义:
tps:该设备每秒的传输次数。”一次传输”意思是”一次I/O请求”。多个逻辑请求可能会被合并为”一次I/O请求”。”一次传输”请求的大小是未知的。
kB_read/s:每秒从设备(drive expressed)读取的数据量;
kB_wrtn/s:每秒向设备(drive expressed)写入的数据量;
kB_read:读取的总数据量;
kB_wrtn:写入的总数量数据量;这些单位都为Kilobytes。

rrqm/s: 每秒进行 merge 的读操作数目。即 delta(rmerge)/s
wrqm/s: 每秒进行 merge 的写操作数目。即 delta(wmerge)/s
r/s: 每秒完成的读 I/O 设备次数。即 delta(rio)/s
w/s: 每秒完成的写 I/O 设备次数。即 delta(wio)/s
rsec/s: 每秒读扇区数。即 delta(rsect)/s
wsec/s: 每秒写扇区数。即 delta(wsect)/s
rkB/s: 每秒读K字节数。是 rsect/s 的一半,因为每扇区大小为512字节。(需要计算)
wkB/s: 每秒写K字节数。是 wsect/s 的一半。(需要计算)
avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)。delta(rsect+wsect)/delta(rio+wio)
avgqu-sz: 平均I/O队列长度。即 delta(aveq)/s/1000 (因为aveq的单位为毫秒)。
await: 平均每次设备I/O操作的等待时间 (毫秒)。即 delta(ruse+wuse)/delta(rio+wio)
svctm: 平均每次设备I/O操作的服务时间 (毫秒)。即 delta(use)/delta(rio+wio)
%util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。即 delta(use)/s/1000 (因为use的单位为毫秒)
如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。


free

free 命令可以显示 Linux 系统中空闲的、已用的物理内存及 swap 内存,及被内核使用的 buffer。

-h 提高可读性
-b:以Byte为单位显示内存使用情况;
-k:以KB为单位显示内存使用情况;
-m:以MB为单位显示内存使用情况;
-o:不显示缓冲区调节列;
-s<间隔秒数>:持续观察内存使用状况;
-t:显示内存总和列;
-V:显示版本信息。

# free -h
              total        used        free      shared  buff/cache   available
Mem:           251G         63G         33G        4.1G        154G        179G
Swap:            0B          0B          0B

Mem 行(第二行)是内存的使用情况。
Swap 行(第三行)是交换空间的使用情况。

total 列显示系统总的可用物理内存和交换空间大小。
used 列显示已经被使用的物理内存和交换空间。
free 列显示还有多少物理内存和交换空间可用使用。
shared 列显示被共享使用的物理内存大小。
buff/cache 列显示被 buffer 和 cache 使用的物理内存大小。
available 列显示还可以被应用程序使用的物理内存大小。

free 列是真正尚未被使用的物理内存数量。
available 列是从应用程序的角度看到的可用内存数量。available = free + buffer + cache,这只是个大约的计算公式,可能有较大误差。

cat /proc/meminfo,cat /proc/meminfo

其实 free 命令中的信息都来自于 /proc/meminfo 文件。/proc/meminfo 文件包含了更多更原始的信息,只是看起来不太直观:


pmap

pmap 命令用于报告进程的内存映射关系,是 Linux 调试及运维一个很好的工具。
pmap [ -x | -d ] [ -q ] pids...

-x, --extended 显示详情
-d:显示设备格式;
-q:不显示头尾行;
-V:显示指定版本。

$ sudo pmap -x 13697
13697:   java -jar /app.jar
Address           Kbytes     RSS   Dirty Mode  Mapping
00000000e3400000   29888   24460   24460 rw---   [ anon ]
0000561859a70000       4       0       0 r---- java
00007fa27e6a8000      28       0       0 r---- libnio.so
00007fa27ef58000    1856       0       0 r--s- rt.jar
ffffffffff600000       4       0       0 r-x--   [ anon ]
---------------- ------- ------- -------
total kB         2003076   76892   41232

Address: 内存开始地址
Kbytes: 占用内存的字节数(KB)
RSS: 保留内存的字节数(KB)
Dirty: 脏页的字节数(包括共享和私有的)(KB)
Mode: 内存的权限:read、write、execute、shared、private (写时复制)
Mapping: 占用内存的文件、或[anon](分配的内存)、或[stack](堆栈)
Offset: 文件偏移
Device: 设备名 (major:minor)

最后一行的值
mapped 表示该进程映射的虚拟地址空间大小,也就是该进程预先分配的虚拟内存大小,即ps出的vsz
writeable/private 表示进程所占用的私有地址空间大小,也就是该进程实际使用的内存大小
shared 表示进程和其他进程共享的内存大小


lsof

https://man7.org/linux/man-pages/man8/lsof.8.html

lsof(list open files)是一个列出当前系统打开文件的工具。

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

lsof [options] filename

安装lsof
yum install lsof

选项
-a 类似 AND 与 操作符,使后面的选项之间是“与”逻辑
-c 列出指定命令所打开的文件;
-g:列出GID号进程详情;
-d<文件号>:列出占用该文件号的进程;
+d<目录>:列出目录下被打开的文件;
+D<目录>:递归列出目录下被打开的文件;
-n<目录>:列出使用NFS的文件;
-p 列出指定进程号所打开的文件;
-P 关闭端口号到端口名的转换,会使命令更快返回
-u:列出UID号进程详情;
-h:显示帮助信息;
-v:显示版本信息。
-w 不显示警告信息

查看文件被哪些进程打开了

lsof server.log,查看哪些进程在使用 server.log 文件,或 lsof|grep server.log

查看所有进程的文件打开数

直接运行 lsof 会列出全部进程打开的文件
lsof |wc -l

-u 查看某用户打开的文件

lsof -u user1,user2,user3 用户可逗号分割多个
lsof -u user1 -u user2 也可以多次使用 -u 参数指定多个用户

-c 查看某个命令打开的文件

lsof -c java 查看 java 命令打开的文件,也可以 lsof|grep java
lsof -c java -c httpd 查看 java 或 httpd 打开的文件

lsof -u root -c java 列出 root 用户 或 java 命令打开的文件,注意 默认多个选项间是 或 的关系

lsof -a -u root -d txt 使用 -a 可以将后续其他选项间改为“与”的关系,查看所属root用户进程所打开的文件类型为txt的文件

-p 查看某进程号打开的文件

lsof -p pid |wc -l 查看指定 pid 打开的文件数
lsof -p pid 查看指定 pid 打开的文件
或者可以直接查看 /proc/pid/fd 目录下进程打开的文件描述符

-i 查看网络连接

-i<条件> 列出符合条件的网络连接,例如 4、6、协议、:端口、 @ip
lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
-i 参数说明:
46 –> IPv4 or IPv6
protocol –> TCP or UDP
hostname –> Internet host name
hostaddr –> IPv4地址
service –> /etc/service中的 service name (可以不只一个)
port –> 端口号 (可以不只一个)

例如:
lsof -i :22 查看打开22端口的进程

lsof -i 列出所有的网络连接

lsof -i tcp 列出所有 tcp 网络连接信息

lsof -i udp:55 列出谁在使用某个特定的udp端口

lsof -i :80lsof -i tcp:80 查看tcp80端口的占用情况

sudo lsof -i -P | grep -i "listen" 查看所有进程监听的端口

+L1 查看已删除但未释放磁盘的文件

在 Linux 中通过 rm 或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink),然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用,这样就会导致我们明明删除了文件,但是磁盘空间却未被释放。

为什么清理日志时不要直接 rm 删除正在写的 log 文件?
如上所述,rm 时发现有进程正在写这个 log 文件就不会真正删除,虽然目录下看不到了,但其实没删除,还在持续写入。
清理正在写入的 log 文件应该使用 >logfile 命令。

使用 lsof 可以查看已删除但仍占用磁盘空间的文件,可用于进一步找出可释放的磁盘空间,同时会打印出打开此文件的进程,方便 kill 进程来释放磁盘空间。

+L 显示文件连接数(如果有的话,socket等本身没有连接数的不会展示)。-L 不显示文件连接数
+L 后不带任何数字,全部连接数的文件都会被列出。
+Ln +L后带数字n,只有连接数小于n的文件会被列出,例如 +L1 会列出连接数小于1,也就是连接数为0的文件,也就是已删除的文件。

例1,lsof +L1 查看已删除未释放磁盘空间的文件

# lsof +L1
COMMAND     PID              USER   FD   TYPE DEVICE SIZE/OFF NLINK       NODE NAME
gunicorn   9061              root    8u   REG 0,1083        0     0  198444324 /tmp/wgunicorn-5wj3aa_e (deleted)
mysqld    79105 systemd-bus-proxy    5u   REG  259,3        0     0  293613569 /var/lib/mysql/ibb7LPoC (deleted)
celery    84919              root  393u   REG 0,1035     4096     0  198445492 /tmp/pymp-v5a0t47l/pym-11-4z4bt7fw (deleted)
gunicorn  85795              root    7u   REG 0,1083        0     0  198444332 /tmp/wgunicorn-r9pvhrkt (deleted)

例2,或者也可以直接通过 deleted 关键字查看已删除的文件
lsof -w|grep deleted 查看已删除但仍占用磁盘空间的文件
lsof -w |grep /data |grep deleted 查看 /data 目录下已删除但仍占用磁盘空间的文件

# lsof -w|grep deleted
COMMAND     PID   TID              USER   FD      TYPE             DEVICE    SIZE/OFF       NODE NAME
mysqld    36259 36704 systemd-bus-proxy    7u      REG              259,3           0  293605025 /var/lib/mysql/ibSsyNnF (deleted)
mysqld    36259 36704 systemd-bus-proxy    8u      REG              259,3           0  293605053 /var/lib/mysql/ibZbEJpD (deleted)
mysqld    36259 36704 systemd-bus-proxy   14u      REG              259,3           0  293605056 /var/lib/mysql/ibzbjh2E (deleted)
mysqld    36259 36704 systemd-bus-proxy  108u      REG              259,3           0  293615468 /var/lib/mysql/MLprHYoC (deleted)
mysqld    36259 36705 systemd-bus-proxy    5u      REG              259,3           0  293603552 /var/lib/mysql/ibS4g0xF (deleted)
mysqld    36259 36705 systemd-bus-proxy    6u      REG              259,3           0  293603553 /var/lib/mysql/ibw42lJF (deleted)
mysqld    36259 36705 systemd-bus-proxy    7u      REG              259,3           0  293605025 /var/lib/mysql/ibSsyNnF (deleted)
mysqld    36259 36705 systemd-bus-proxy    8u      REG              259,3           0  293605053 /var/lib/mysql/ibZbEJpD (deleted)

lsof: no pwd entry for UID 33

原因是要列出的进程是在容器内启动的,加 -w 参数可过滤掉这些信息

返回结果解析

lsof -c run.sh
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
run.sh  33234 prouser  cwd    DIR  253,7     4096 599439 /opt/app/jboss-eap-5.2/jboss-as/server/aisServer3/bin
run.sh  33234 prouser  rtd    DIR  253,1     4096      2 /
run.sh  33234 prouser  txt    REG  253,1   939344 122884 /bin/bash
run.sh  33234 prouser  mem    REG  253,1   157072  41353 /lib64/ld-2.12.so
run.sh  33234 prouser    0r   CHR    1,3      0t0   4405 /dev/null
run.sh  33234 prouser    1w   REG  253,7 20671770 598689 /opt/app/jboss-eap-5.2/jboss-as/server/aisServer3/bin/startServer.log
run.sh  33234 prouser    2w   REG  253,7 20671770 598689 /opt/app/jboss-eap-5.2/jboss-as/server/aisServer3/bin/startServer.log
run.sh  33234 prouser  255r   REG  253,7    10675 557207 /opt/app/jboss-eap-5.2/jboss-as/bin/run.sh

COMMAND:进程的名称
PID:进程标识符
USER:进程所有者
FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等。txt类型的文件是程序代码。数值表示应用程序的文件描述符,这是打开该文件时返回的一个整数,数值后跟打开模式,u表示该文件被打开并处于读取/写入模式,而不是只读(r)或只写(w)模式。同时还有大写的W 表示该应用程序具有对整个文件的写锁。初始打开每个应用程序时,都具有三个文件描述符,从 0 到 2,分别表示标准输入、输出和错误流。所以大多数应用程序所打开的文件的 FD 都是从 3 开始。
TYPE:文件类型,如DIR、REG等。文件和目录分别称为 REG 和 DIR。而CHR 和 BLK,分别表示字符和块设备;或者 UNIX、FIFO 和 IPv4,分别表示 UNIX 域套接字、先进先出 (FIFO) 队列和网际协议 (IP) 套接字。
DEVICE:指定磁盘的名称
SIZE:文件的大小
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称

每天一个linux命令(51):lsof命令
http://www.cnblogs.com/peida/archive/2013/02/26/2932972.html


lscpu

lscpu,查看cpu统计信息

[jboss5@vm-vmw1891-jbs]~>lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    1
Core(s) per socket:    1
CPU socket(s):         4
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 47
Stepping:              2
CPU MHz:               1995.000
BogoMIPS:              3990.00
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              24576K
NUMA node0 CPU(s):     0-3

cat /proc/cpuinfo,可以知道每个cpu信息,如每个CPU的型号,主频等。

查看cpu核数

总核数 = 物理CPU个数 X 每颗物理CPU的核数
总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数

# 查看物理CPU个数
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l

# 查看每个物理CPU中core的个数(即核数)
cat /proc/cpuinfo| grep "cpu cores"| uniq

# 查看逻辑CPU的个数
cat /proc/cpuinfo| grep "processor"| wc -l

fuser

fuser可以显示出当前哪个程序在使用磁盘上的某个文件、挂载点、甚至网络端口,并给出程序进程的详细信息。

-a:显示所有命令行中指定的文件,默认情况下被访问的文件才会被显示。
-c:和-m一样,用于POSIX兼容。
-k:杀掉访问文件的进程。如果没有指定-signal就会发送SIGKILL信号。
-i:杀掉进程之前询问用户,如果没有-k这个选项会被忽略。
-l:列出所有已知的信号名称。
-m:name 指定一个挂载文件系统上的文件或者被挂载的块设备(名称name)。这样所有访问这个文件或者文件系统的进程都会被列出来。如果指定的是一个目录会自动转换成”name/“,并使用所有挂载在那个目录下面的文件系统。
-n:space 指定一个不同的命名空间(space).这里支持不同的空间文件(文件名,此处默认)、tcp(本地tcp端口)、udp(本地udp端口)。对于端口, 可以指定端口号或者名称,如果不会引起歧义那么可以使用简单表示的形式,例如:name/space (即形如:80/tcp之类的表示)。
-s:静默模式,这时候-u,-v会被忽略。-a不能和-s一起使用。
-signal:使用指定的信号,而不是用SIGKILL来杀掉进程。可以通过名称或者号码来表示信号(例如-HUP,-1),这个选项要和-k一起使用,否则会被忽略。
-u:在每个PID后面添加进程拥有者的用户名称。
-v:详细模式。输出似ps命令的输出,包含PID,USER,COMMAND等许多域,如果是内核访问的那么PID为kernel. -V 输出版本号。
-4:使用IPV4套接字,不能和-6一起应用,只在-n的tcp和udp的命名存在时不被忽略。
-6:使用IPV6套接字,不能和-4一起应用,只在-n的tcp和udp的命名存在时不被忽略。

每个进程号后面都跟随一个字母,该字母指示进程如何使用文件。
c:指示进程的工作目录。
e:指示该文件为进程的可执行文件(即进程由该文件拉起)。
f:指示该文件被进程打开,默认情况下f字符不显示。
F:指示该文件被进程打开进行写入,默认情况下F字符不显示。
r:指示该目录为进程的根目录。
m:指示进程使用该文件进行内存映射,抑或该文件为共享库文件,被进程映射进内存。

示例:

fuser -um /data 显示使用目录 /data 的进程信息

sudo fuser -um /var/log/nginx/access.log 显示使用 access.log 文件的进程

$ sudo fuser -um /var/log/nginx/access.log
/var/log/nginx/access.log:     1rce(root)     2rc(root)     3rc(root)     5rc(root)     7rc(root)     8rc(root)     9rc(root)    10rc(root)    11rc(root)    14rc(root)    15rc(root)    16rc(root)    18rc(root)    19rc(root)    20rc(root)    21rc(root)    22rc(root)    23rc(root)    24rc(root)    25rc(root)    26rc(root)    27rc(root)    32rc(root)    33rc(root)    34rc(root)    35rc(root)    43rc(root)    45rc(root)    46rc(root)    47rc(root)    49rc(root)    62rc(root)   113rc(root)   178rc(root)   179rc(root)   676rc(root)   709rc(root)   710rc(root)   737rc(root)   746rc(root)  1679rc(root)  1684rc(root)  1685rc(root)  1692rc(root)  1694rc(root)  1697rc(root)  1698rc(root)  1699rc(root)  1700rc(root)  1701rc(root)  1702rc(root)  1703rc(root)  1781rce(root)  1803rce(root)  1817rce(root)  2512rc(root)  3363rce(postfix)  3457rce(root)  3483rce(rpc)  3488rce(polkitd)  3490rce(dbus)  3494rce(root)  3504rce(chrony)  3508rce(root)  3592rce(root)  3610rce(centos)  3619rce(centos)  3771rce(root)  3810rce(root)  3840rce(root)  3847rce(root)  3970rce(root)  3972rce(postfix)  4009rce(root)  4010rce(root)  4012rce(root)  4019rce(root)  4020rce(root)  4022rce(root)  4033rce(nobody)  4711re(root)  4727m (未知)   5464rce(mysql)  5747rce(mysql)  8564rce(centos) 13681re(root) 13697m(root) 13907re(root) 13923cm(nfsnobody) 13982re(root) 13998m(centos) 14114m(centos) 14349re(root) 14365m(root) 14424re(root) 14440m(root) 14706re(root) 14723m(centos) 14739m(centos) 16160rc(root) 20860re(root) 20876m(root) 20900m (未知)  21453rce(postfix) 22024re(root) 22040m(root) 23613rc(root) 23999rc(root) 29047rc(root) 30361re(root) 30377m(root) 30439m(root) 30440m(root) 30441m(root) 30442m(root) 30443m(centos) 30444m(root) 31777rc(root)

fuser -m -k -i readme 杀掉打开readme文件的程序

fuser -v 8306/tcpfuser -v -n tcp 80 查看那些程序使用tcp的8306端口


time

time 命令用于统计给定命令所花费的总时间。
当测试一个程序或比较不同算法时,执行时间是非常重要的,一个好的算法应该是用时最短的。所有类UNIX系统都包含time命令,使用这个命令可以统计时间消耗。例如:

$ time date
2019年 09月 05日 星期四 23:34:33 CST
real    0m0.003s
user    0m0.001s
sys    0m0.000s

输出的信息分别显示了该命令所花费的real时间、user时间和sys时间。
real 时间是指挂钟时间,也就是命令开始执行到结束的时间。这个短时间包括其他进程所占用的时间片,和进程被阻塞时所花费的时间。
user 时间是指进程花费在用户模式中的CPU时间,这是唯一真正用于执行进程所花费的时间,其他进程和花费阻塞状态中的时间没有计算在内。
sys 时间是指花费在内核模式中的CPU时间,代表在内核中执系统调用所花费的时间,这也是真正由进程使用的CPU时间。

例如统计一个sql脚本的执行时间

time mysql -h localhost -uroot -ppwd database_name < prod.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
real    6m13.689s
user    0m30.067s
sys    0m11.806s

strace

strace 命令是一个集诊断、调试、统计与一体的工具,我们可以使用strace对应用的系统调用和信号传递的跟踪结果来对应用进行分析,以达到解决问题或者是了解应用工作过程的目的。
strace 常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

yum 安装 strace
yum -y install strace

-tt 在输出中的每一行前加上时间信息,微秒级.
-T 显示每一调用所耗的时间.
-e expr
指定一个表达式,用来控制如何跟踪.格式如下:
[qualifier=][!]value1[,value2]…
qualifier 只能是 trace,abbrev,verbose,raw,signal,read,write 其中之一
value 是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-eopen 等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\.
-o filename
将strace的输出写入文件filename

指定 pid 跟踪
trace -T -tt -e trace=all -p 28979

输出
strace 输出的每一行都是一条系统调用,等号左边是系统调用的函数名及其参数,右边是该调用的返回值。 strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。


网络相关

netstat

netstat命令的功能是显示网络连接、路由表和网络接口信息,可以让用户得知有哪些网络连接正在运作

使用时如果不带参数,netstat显示活动的 TCP 连接。
-a, --all 显示所有 socket 连接,默认只显示 connected 已连接的(不显示 LISTEN 的)
-n, --numeric 拒绝显示别名,能显示数字的全部转化成数字。
-p, --programs 显示建立相关链接的程序名或pid

-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-l 仅列出有在 Listen (监听) 的服務状态
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c, --continuous 每隔一个固定时间,执行该netstat命令。

常用:
netstat -anp | grep xxx
netstat -antpl |grep xxx

从整体上看,netstat 的输出结果可以分为两个部分:
一个是Active Internet connections,称为有源TCP连接,
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
其中”Recv-Q”和”Send-Q”指%0A的是接收队列和发送队列。这些数字一般都应该是0。如果不是则表示软件包正在队列中堆积。这种情况只能在非常少的情况见到。

另一个是Active UNIX domain sockets,称为有源Unix域套接口(和网络套接字一样,但是只能用于本机通信,性能可以提高一倍)。
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags Type State I-Node Path
Proto显示连接使用的协议,RefCnt表示连接到本套接口上的进程号,Types显示套接口的类型,State显示套接口当前的状态,Path表示连接到套接口的其它进程使用的路径名。

查看某端口占用情况

方法1,用 netstat -anp

$ sudo netstat -anp |grep :23
tcp        0      0 :::23                       :::*                        LISTEN      7328/xinetd

同时查多个端口,比如验证 邮件相关的 smtp 25端口 imap的 143 接口 和 pop3 的110 接口

$ sudo netstat -anp|egrep ':25|:110|:143'
tcp        0      0 0.0.0.0:110                 0.0.0.0:*                   LISTEN      28182/dovecot
tcp        0      0 0.0.0.0:143                 0.0.0.0:*                   LISTEN      28182/dovecot
tcp        0      0 0.0.0.0:25                  0.0.0.0:*                   LISTEN      4640/sendmail
tcp        0      0 :::110                      :::*                        LISTEN      28182/dovecot
tcp        0      0 :::143                      :::*                        LISTEN      28182/dovecot

方法2,用 lsof

$ sudo lsof -i:23
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
xinetd  7328 root    5u  IPv6 524265      0t0  TCP *:telnet (LISTEN)

方法3,用 ss -anp

$ ss -anp|grep 8001
tcp    LISTEN     0      100      :::8001                 :::*
tcp    ESTAB      0      0       ::1:38752               ::1:8001
tcp    ESTAB      0      0       ::1:8001                ::1:38752

netstat结果中的TCP连接状态

LISTEN: 侦听来自远方的TCP端口的连接请求;
SYN-SENT: 在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED: 在收到和发送一个连接请求后等待对方对连接请求的确认;
ESTABLISHED: 代表一个打开的连接;
FIN-WAIT-1: 等待远程TCP连接中断请求, 或先前的连接中断请求的确认;
FIN-WAIT-2: 从远程TCP等待连接中断请求;
CLOSE-WAIT: 等待从本地用户发来的连接中断请求;
CLOSING: 等待远程TCP对连接中断的确认;
LAST-ACK: 等待原来的发向远程TCP的连接中断请求的确认;
TIME-WAIT: 等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSE: 没有任何连接状态;

查看已建立的连接数

netstat -anp|grep ESTABLISHED |grep auth_server|wc 查看已建立的连接数
netstat -anp|grep -vi listen |wc 查看非 listen 状态的连接数

-c 持续查看连接

netstat -anpc|grep 8768 持续刷新执行此 netstat 命令


ss

ss 是 Socket Statistics 的缩写。顾名思义,ss 命令可以用来获取 socket 统计信息,它可以显示和 netstat 类似的内容。但 ss 的优势在于它能够显示更多更详细的有关 TCP 和连接状态的信息,而且比 netstat 更快速更高效。

当服务器的 socket 连接数量变得非常大时,无论是使用 netstat 命令还是直接 cat /proc/net/tcp 执行速度都会很慢。

ss 快的秘诀在于,它利用到了 TCP 协议栈中 tcp_diag。tcp_diag 是一个用于分析统计的模块,可以获得 Linux 内核中第一手的信息,这就确保了 ss 的快捷高效。当然,如果你的系统中没有 tcp_diag,ss 也可以正常运行,只是效率会变得稍慢。

-a, --all 显示所有套接字(sockets)
-n, --numeric 不解析服务名称
-p, --processes 显示使用套接字(socket)的进程
-t, –tcp 仅显示 TCP套接字(sockets)
-u, –udp 仅显示 UCP套接字(sockets)
-s, –summary 显示套接字(socket)使用概况
-l, –listening 显示监听状态的套接字(sockets)

ss -anp 查看端口占用

ss -anp 查看端口占用

# ss -anp |grep 8081
Netid  State      Recv-Q Send-Q Local Address:Port    Peer Address:Port
tcp    TIME-WAIT  0      0      127.0.0.1:33436       127.0.0.1:8081
tcp    TIME-WAIT  0      0      127.0.0.1:58298       127.0.0.1:8081
tcp    LISTEN     0      100    :::8081               :::*                      users:(("java",pid=16998,fd=572))
tcp    ESTAB      0      0      ::ffff:127.0.0.1:8081 ::ffff:127.0.0.2:50602    users:(("java",pid=16998,fd=579))

ss -s 查看socket统计

例2、ss -s 显示 socket 摘要

# ss -s
Total: 3332 (kernel 464332)
TCP:   3253 (estab 1355, closed 1079, orphaned 0, synrecv 0, timewait 453/0), ports 0

Transport Total     IP        IPv6
*      464332    -         -
RAW      0         0         0
UDP      78        18        60
TCP      2174      668       1506
INET      2252      686       1566
FRAG      0         0         0

traceroute

traceroute命令用于追踪数据包在网络上的传输时的全部路径,它默认发送的数据包大小是40字节。
traceroute通过发送小的数据包到目的设备直到其返回,来测量其需要多长时间。一条路径上的每个设备traceroute要测3次。输出结果中包括每次测试的时间(ms)和设备的名称(如有的话)及其ip地址。

traceroute IP或域名


dig

Dig是一个在类Unix命令行模式下查询DNS包括NS记录,A记录,MX记录等相关信息的工具。
dig默认的查询是查询A记录

常用:dig github.com +nocomments +noauthority +noadditional
精简:dig github.com +short

Dig HOWTO 中文手册–dig命令使用大全
http://www.cnblogs.com/daxian2012/archive/2013/01/10/2854126.html


ping

ping命令用来测试主机之间网络的连通性。
执行ping指令就是发送 ICMP ECHO_REQUEST 包给目标host,若远端主机的网络功能没有问题,就会返回 ICMP ECHO_RESPONSE 包给源主机,因而得知该主机运作正常。

1、ping 在应用层,但是直接使用网络层的ICMP协议,跳过了传输层。
2、ping 命令只能测试ip或域名通不通,不能ping端口,想测试端口通不通要用telnet
3、ping 的主机参数不能包含协议,比如 ping www.baidu.com 但不能 ping http://www.baidu.com,会显示 unknown host

tcpping

tcpping 工具工作在 TCP 层,通过发送伪造的 TCP SYN 包并侦听来自服务器或中间设备返回的 SYN/ACK 或 RST 。
代码100多行,源代码在此链接 http://www.vdberg.org/~richard/tcpping , tcpping需要调用 tcptraceroute , 打印与ping近乎相同测试结果,目前版本为V1.7
tcping的介绍参考链接 http://www.vdberg.org/~richard/tcpping.html , 这个是Richard van den Berg在2002年编写的,作者当时需要测量TCP往返时间。所以写了这个脚本。
tcpping只支持Linux。不支持Windows平台。

tcpping 安装
1、 tcpping 脚本依赖 tcptraceroute 组件,所以必须先安装 tcptraceroute
yum install tcptraceroute

2、 下载tcpping文件
wget http://www.vdberg.org/~richard/tcpping

3、将 tcpping 文件移动到 /usr/bin 下并授权。

# mv tcpping /usr/bin/
# cd /usr/bin
# chmod 755 tcpping

参数 参数描述
-d 在每个结果输出前打印时间戳
-c 将结果输出在一列
-C 输出与fping的-C选项相同的打印格式
-w Wait time in seconds (defaults to 3)
-r -r n:每n秒重复一次(默认为1)
-x 重复n次(默认为无限制)

几款 ping tcping 工具总结
https://www.cnblogs.com/jonnyan/p/9662791.html


telnet

telnet 命令用于登录远程主机,对远程主机进行管理。telnet 因为采用明文传送报文,安全性不好,很多 Linux 服务器都不开放 telnet 服务,而改用更安全的 ssh 方式了。
telnet IP 端口

MAC 安装 telnet

brew install telnet
默认安装到 /usr/local/Cellar/telnet/63

退出 telnet

Ctrl + ] 回到 telnet 命令行,然后输入 quit 命令即可退出。

telnet 测试 TRACE/TRACK 方法

telnet ip port 登录 telnet 后,输入命令 TRACE /

有响应 HTTP/1.1 200 OK 表示支持 TRACE/TRACK 方法

# telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
TRACE /     
HTTP/1.1 200 OK
content-type: text/html;charset=UTF-8
content-length: 61

{"code":500,"msg":"invalid request, HttpMethod not support."}

返回 405 Method Not Allowed 说明不支持 TRACE/TRACK 方法

# telnet 127.0.0.1 8768
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
trace /
{"timestamp":"2023-12-25 08:18:01","status":405,"error":"Method Not Allowed","path":"/"}

Linux 测试端口连通性

telnet 测试端口连通性

出现:
Connected to x.x.x.x.
Escape character is ‘^]’.
表示端口是通的,此时按 Ctrl + ] 会呼出 telnet 的命令行,出来 telnet 命令行之后就可以执行 telnet 命令。
想退出 telnet 也是先按 Ctrl + ],出来 telnet 命令行后输入 quit 退出。

例1,在服务器 10.6.144.210 上 telnet 数据库端口,端口通:

$ telnet 10.6.143.244 5443
Trying 10.6.143.244...
Connected to 10.6.143.244.
Escape character is '^]'.
^CConnection closed by foreign host.

例2,不通的端口是如下返回:

$ telnet 10.6.143.244 1234
Trying 10.6.143.244...
telnet: connect to address 10.6.143.244: Connection refused

ssh -v -p 测试端口连通性

ssh -v -p port username@ip
-v 调试模式(会打印日志)
-p 指定端口

能看到 Connection established 表示端口是通的

例1,端口通

# ssh -v -p 8778 127.0.0.1
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017
debug1: Reading configuration data /root/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
debug1: Connecting to 127.0.0.1 [127.0.0.1] port 8778.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/id_rsa type 1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_rsa-cert type -1

例2,端口不通:

# ssh -v -p 8401 10.153.108.21
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017
debug1: Reading configuration data /root/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
debug1: Connecting to 10.153.108.21 [10.153.108.21] port 8401.
debug1: connect to address 10.153.108.21 port 8401: Connection timed out
ssh: connect to host 10.153.108.21 port 8401: Connection timed out

curl 测试端口连通性

例1,端口不通:

curl 10.153.108.21:8401
curl: (7) Failed connect to 10.153.108.21:8401; 拒绝连接

例2,端口通:

curl 127.0.0.1:8778
{"timestamp":"2021-08-31 10:57:42","status":404,"error":"Not Found","message":"No message available","path":"/"}

wget 测试端口连通性

例1,端口不通:

wget 10.153.108.21:8401
--2021-08-31 10:55:20--  http://10.153.108.21:8401/
正在连接 10.153.108.21:8401... 失败:拒绝连接。

例2,端口通:

# wget 127.0.0.1:8778
--2021-08-31 10:59:03--  http://127.0.0.1:8778/
正在连接 127.0.0.1:8778... 已连接。
已发出 HTTP 请求,正在等待回应... 404
2021-08-31 10:59:03 错误 404:(没有描述)。

ifconfig

配置和显示Linux内核中网络接口的网络参数。ifconfig的配置时临时性的,在网卡重启或机器重启后配置会消失,若想配置永久生效,需修改网卡的配置文件。

ifconfig [网络设备] [参数]

  • -a,显示全部接口信息
  • up,启动指定网络设备/网卡。
  • down,关闭指定网络设备/网卡。

查询结果

eth0      Link encap:Ethernet  HWaddr 00:0C:29:92:DB:6A
          inet6 addr: fe80::20c:29ff:fe92:db6a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:473 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:39260 (38.3 KiB)  TX bytes:468 (468.0 b)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

第一行:连接类型:Ethernet(以太网)HWaddr(硬件mac地址)
第二行:网卡的IP地址、子网、掩码
第三行:UP(代表网卡开启状态)RUNNING(代表网卡的网线被接上)MULTICAST(支持组播)MTU:1500(最大传输单元):1500字节
第四、五行:接收、发送数据包情况统计
第七行:接收、发送数据字节数统计信息。

eth0表示第一块网卡
lo是表示主机的回坏地址,这个一般是用来测试一个网络程序,但又不想让局域网或外网的用户能够查看,只能在此台主机上运行和查看所用的网络接口。比如把 httpd服务器的指定到回坏地址,在浏览器输入127.0.0.1就能看到你所架WEB网站了。

激活网卡eth0:ifconfig eth0 up


hostname

hostname 命令用于显示和设置系统的主机名称。
环境变量 $HOSTNAME 也保存了当前的主机名。
在使用 hostname 命令设置主机名后,系统并不会永久保存新的主机名,重新启动机器之后还是原来的主机名。如果需要永久修改主机名,需要同时修改 /etc/hosts/etc/sysconfig/network 的相关内容。

-i, --ip-address IP 地址
-f, --fqdn, --long 长 hostname

hostname,显示当前主机名
hostname masi-dell,临时设置主机名为masi-dell

hostname -i 查看机器 ip


nslookup

nslookup 命令是常用域名查询工具,就是查DNS信息用的命令。

nslookup4有两种工作模式,即“交互模式”和“非交互模式”:
1、交互模式
进入交互模式:直接输入nslookup命令,不加任何参数,则直接进入交互模式,此时nslookup会连接到默认的域名服务器(即 /etc/resolv.conf 的第一个dns地址)。
在“交互模式”下,用户可以向域名服务器查询各类主机、域名的信息,或者输出域名中的主机列表。

2、非交互模式
在“非交互模式”下,用户可以针对一个主机或域名仅仅获取特定的名称或所需信息。例如输入nslookup -nameserver/ip。进入非交互模式,就直接输入nslookup 域名就可以了。

nslookup www.baidu.com 根据域名查 ip

$ nslookup www.baidu.com
Server:        172.22.1.253
Address:    172.22.1.253#53

www.baidu.com    canonical name = www.a.shifen.com.
Name:    www.a.shifen.com
Address: 61.135.185.32
Name:    www.a.shifen.com
Address: 61.135.169.121

nslookup 172.22.1.253 根据 ip 查域名

nslookup 172.22.1.253
Server:        172.22.1.253
Address:    172.22.1.253#53

253.1.22.172.in-addr.arpa    name = centos-7.x

hostnamectl


ip

ip命令 用来显示或操纵Linux主机的路由、网络设备、策略路由和隧道,是Linux下较新的功能强大的网络配置工具。
它整合了 ifconfig 与 route 这两个命令,非常强大。

ip link 显示网卡信息

ip a 显示所有 ip 信息

ip r查看默认网关

ip rip route 有 default 的就是默认网关

default via 192.168.0.1 dev wlp58s0 proto dhcp metric 600
169.254.0.0/16 dev wlp58s0 scope link metric 1000
192.168.0.0/24 dev wlp58s0 proto kernel scope link src 192.168.0.106 metric 600

route

route 命令用于显示和操作IP路由表

[centos@lightsail ~]$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.26.0.1      0.0.0.0         UG    0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.26.0.0      0.0.0.0         255.255.240.0   U     0      0        0 eth0

查看机器是否有默认网关

route -n 结果中是否有 Destination 是 0.0.0.0 的这一行,有就是有默认网关,没有就是没默认网关
默认网关就是当数据包不匹配任何设定的路由规则时所去向的地址。


curl

curl man page
https://curl.se/docs/manpage.html

curl 命令是一个利用 URL 规则在命令行下工作的文件传输工具。它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称 curl 为下载工具。作为一款强力工具,curl支持包括HTTP、HTTPS、ftp等众多协议,还支持POST、cookies、认证、从指定偏移处下载部分文件、用户代理字符串、限速、文件大小、进度条等特征。

如果系统没有curl可以使用 yum install curl 安装,也可以下载安装。

curl是利用URL语法在命令行方式下工作的开源文件传输工具

-X, --request COMMAND 指定什么命令,默认是 GET 命令,常用 -X POST
-H, --header LINE 自定义头信息传递给服务器
-d, --data DATA HTTP POST方式传送数据
-i, --include 输出时包括protocol头信息
-v, --verbose 输出更多信息
-L, --location 跟踪重定向 (H)
-O, --remote-name 把输出写到该文件中,保留远程文件的文件名
-k, --insecure 允许连接到无认证的 ssl 站点
-V 查看 curl 版本及支持的协议
-I, --head 只取回 header
-0, --http1.0 强制使用 HTTP 1.0 版本
-s, --silent 不输出进度条,不输出结果外的其他信息,方便直接 grep curl
--connect-timeout SECONDS 连接超时时间,单位秒
-m, --max-time SECONDS 传输超时时间,单位秒

1、GET 请求

curl -X GET \
  https://postman-echo.com/headers \
  -H 'Postman-Token: 498efa2b-4226-406f-aad3-4c9305e2e37b' \
  -H 'cache-control: no-cache' \
  -H 'my-sample-header: Lorem ipsum dolor sit amet'

2、Form 表单格式 POST 请求

curl -X POST "http://test.apis.com/user/v1/users?app_id=1000&sign=33a130f9425063421cd9e7b6ed6050a5" \
-H 'Authorization: Bearer 2.0plV407kIBLsKUC1Ksuu9Dz6H5XO0it6SXmqqxpP4Ehw=' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: 77f950d6-cb9e-4da8-a2b8-3aee0c1db608' \
-H 'cache-control: no-cache' \
-d 'mobile=15216719185&country_code=86&name=张三&source=register' -v

3、json 格式 POST 请求

curl -X POST localhost:8080/api/v1/user -H 'Content-Type:application/json' -d '{}'

4、多 query 参数请求用引号包住
例如:
curl “http://192.168.25.169:8080/?hostname=CHN-YL-g-3WI&type=ccms&domain=rtmp://livertmp.wasu.cn&clientcount=50&bandwidth=30000"
如果不加引号,curl 命令会将 query 参数截断,只剩下第一个参数,即 http://192.168.25.169:8080/?hostname=CHN-YL-g-3WI
解决:不同参数间的&前加转义字符\,或者将整个url用引号包住

curl 命令行工具的使用及命令参数说明
https://itbilu.com/linux/man/4yZ9qH_7X.html

curl 读 json 文件

如果 curl body 参数过长,比如把图片 base64 放到 body 中,会报错 argument list too long
解决方法:
把 body 写入文件 body.json

cat body.json |curl -X POST localhost:8080/api -H 'Content-Type: application/json' -d @-
或
curl -X POST localhost:8080/api -H 'Content-Type: application/json' -d @body.json

-d @- -d 指明请求体,@- 代表从标准输入读取数据, @文件名 表示读取文件

curl 默认不支持https

curl 默认安装完后是只支持 http 协议而不支持 https 协议的。

访问 https 连接报错
curl: (1) Protocol “https” not supported or disabled in libcurl

curl: (51) Unable to communicate securely with peer: requested domain name does not match the server’s certificate.

curl: (60) SSL certificate problem: self signed certificate

curl -V 查看 curl 版本及支持的协议

# curl -V
curl 7.61.0 (x86_64-pc-linux-gnu) libcurl/7.61.0 zlib/1.2.8
Release-Date: 2018-07-11
Protocols: dict file ftp gopher http imap pop3 rtsp smtp telnet tftp
Features: AsynchDNS Largefile libz UnixSockets

# curl -V
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.19.1 Basic ECC zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz

临时解决:
-k, --insecure 关闭 https 校验
curl -X POST https://xx-domain:8001/api -k

curl 测试 TRACE/TRACK 方法

只加 -X TRACE 看不出对这两个方法的响应,需要加 -v 输出详情才能看到对 TRACE/TRACK 方法的响应,能看到 < HTTP/1.1 200 OK 就是支持 TRACE/TRACK 方法,虽然最后还是会返回 {“code”:500,”msg”:”invalid request, HttpMethod not support.”}

# curl 127.0.0.1:8080 -v -X TRACE
* About to connect() to 127.0.0.1 port 8080 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> TRACE / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< content-type: text/html;charset=UTF-8
< content-length: 61
< connection: keep-alive
< 
* Connection #0 to host 127.0.0.1 left intact
{"code":500,"msg":"invalid request, HttpMethod not support."}

下面这种返回 405 Method Not Allowed 说明不支持 TRACE/TRACK 方法

# curl -v -X TRACE 127.0.0.1:8768
* About to connect() to 127.0.0.1 port 8768 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8768 (#0)
> TRACE / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8768
> Accept: */*
> 
< HTTP/1.1 405 
< Allow: HEAD, DELETE, POST, GET, OPTIONS, PUT
< Content-Type: message/http
< Content-Length: 87
< Date: Mon, 25 Dec 2023 00:10:51 GMT
< 
TRACE /error HTTP/1.1
user-agent: curl/7.29.0
host: 127.0.0.1:8768
accept: */*
* Connection #0 to host 127.0.0.1 left intact

option –data-raw: is unknown

postman 请求拷贝为 curl 命令后执行报错 –data-raw: is unknown
原因是有的 curl 版本中没有 –data-raw 选项
直接使用 -d,–data 代替 –data-raw 即可
后来新版本的 postman 拷贝出 curl 命令中已经改为 -d 了

-s grep curl 结果

curl 接 grep 使用时,会打出进度信息,很烦人。
增加 -s 静默参数可以关闭进度信息输出,方便接 grep 使用

#curl https://httpbin.org/get |grep Host
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   257  100   257    0     0    224      0  0:00:01  0:00:01 --:--:--   226
    "Host": "httpbin.org",

#curl -s https://httpbin.org/get |grep Host
    "Host": "httpbin.org",

curl 超时时间设置

1、curl 可配置超时参数
--connect-timeout SECONDS 连接超时时间,单位秒
-m, --max-time SECONDS 传输超时时间,单位秒

2、或者下面这些环境变量可以设置 crul 的超时时间
CURLOPT_FTP_RESPONSE_TIMEOUT: No default (indefinite)
CURLOPT_TIMEOUT: No default (indefinite)
CURLOPT_TIMEOUT_MS: No default (indefinite)
CURLOPT_CONNECTTIMEOUT: Defaults to 300 seconds
CURLOPT_CONNECTTIMEOUT_MS: No default
CURLOPT_ACCEPTTIMEOUT_MS: Defaults to 60000 ms

具体解释见 curl 手册
https://curl.se/libcurl/c/curl_easy_setopt.html


wget

GNU wget man page
https://www.gnu.org/software/wget/manual/wget.html

linux 中一个下载文件的工具。
在下载的过程中会显示进度条,包含(下载完成百分比,已经下载的字节,当前下载速度,剩余下载时间)
如果系统中没有 wget 工具,yum -y install wget 安装即可。

-q, –quiet 安静模式(没有输出)
-o, –output-file=FILE 把记录写到 FILE 文件中
-O –output-document=FILE 把文档写到 FILE 文件中

使用wget下载单个文件
wget http://www.minjieren.com/wordpress-3.1-zh_CN.zip

使用wget -O下载并以不同的文件名保存
wget -O wordpress.zip http://www.minjieren.com/download.aspx?id=1080
wget默认会以最后一个符合”/”的后面的字符来命令,对于动态链接的下载通常文件名会不正确。

curl与wget的区别

wget是个专职的下载利器,简单,专一,极致;
而curl可以下载,但是长项不在于下载,而在于模拟提交web数据,POST/GET请求,调试网页,等等。
在下载上,也各有所长,wget可以递归,支持断点;而curl支持URL中加入变量,因此可以批量下载。
经常用wget来下载文件,加 -c 选项不怕断网;使用curl 来跟网站的API 交互,简便清晰。

wget 发送POST json请求

发送 json 数据
--body-data=Data-String 使用 --method 指定方法后必须设置,用于发送 json 请求
--body-file=Data-File
参数之间用空格或等号都可以。
例如

wget --method POST \
--header "Content-Type: application/json" \
--header="token:1234567" \
http://example.com/api/data \
--body-data '{
    "msgCode":"12345",
    "msgType":"ALERT",
    "msgId":"2"
  }'

但有些版本的 wget 不支持 –method 参数。

wget 设置header

wget的header参数,可以多次设置
wget --header="k:v" --header="k2:v2" url -O file


nc netcat

NetCat(nc) 是一个简单、可靠的网络工具,可通过 TCP 或 UDP 协议传输读写数据,被称为网络工具中的“瑞士军刀”。

-g<网关> 设置路由器跃程通信网关,最多可设置8个。
-G<指向器数目> 设置来源路由指向器,其数值为4的倍数。
-h 在线帮助。
-i<延迟秒数> 设置时间间隔,以便传送信息及扫描通信端口。
-l 使用监听模式,管控传入的资料。
-o<输出文件> 指定文件名称,把往来传输的数据以16进制字码倾倒成该文件保存。
-p<通信端口> 设置本地主机使用的通信端口。
-r 乱数指定本地与远端主机的通信端口。
-s<来源位址> 设置本地主机送出数据包的IP地址。
-u 使用UDP传输协议。
-z 使用 0 I/O, 连接成功后立即关闭连接,不进行数据交换
-v 显示指令执行过程,即详细输出。
-n 直接使用IP地址,而不通过域名服务器。
-w<超时秒数> 设置等待连线的时间。

端口扫描

端口扫描经常被系统管理员和黑客用来发现在一些机器上开放的端口,帮助他们识别系统中的漏洞。
nc -z -v -n -w2 172.31.100.7 1-4000 打印 1 到 4000 范围内所有开放的 tcp 端口
可以运行在TCP或者UDP模式,默认是TCP,-u参数调整为udp

聊天服务器

服务端 nc -l 1567 在 1567 端口启动了一个 tcp 服务器,所有的标准输出和输入会输出到该端口。输出和输入都在此 shell 中展示。
客户端 nc 127.0.0.1 1567 连接指定 ip:port, 之后两台机器不管键入什么都会出现在另一台服务器上。

远程拷贝文件

从 server1 拷贝文件到 server2 上。
server2 nc -l 1234 > 1234.txt 在端口 1234 上启动监听并将内容重定向到指定文件
server1 nc 127.0.0.1 1234 < abc.txt 连接指定 ip:port, 并将 abc.txt 内容输入重定向,回车后就会存入 server2 的 1234.txt 上。


socat

socat(SOcket CAT) 是一个多用途双向数据转接工具。
http://www.dest-unreach.org/socat/

socat 功能跟 NetCat 类似,但更安全(支持 chroot),兼容多种协议,支持操作文件(file)、管道(pipe)、设备(device)、TCP 套接字、 Unix 套接字、 SOCKS 客户端、 CONNECT 代理以及 SSL 等等。
socat 是 netcat 实用程序的出色替代品。

yum 安装 socat yum install -y socat
Mac brew 安装 socat brew install socat

基本语法
socat [options] <address> <address>
address 是文件描述符,Socat 所做的工作就是在 2 个 address 指定的描述符间建立一个 pipe 用于发送和接收数据。几个常用的 address 描述方式如下:
-,STDIN,STDOUT 表示标准输入输出,可以就用一个横杠代替。
/var/log/syslog 打开一个文件作为数据流,可以是任意路径。
TCP:: 建立一个 TCP 连接作为数据流,TCP 也可以替换为 UDP 。
TCP-LISTEN: 建立 一个 TCP 监听端口,TCP 也可以替换为 UDP。
EXEC: 执行一个程序作为数据流。
以上规则中前面的 TCP 等都可以小写,在这些描述后可以附加一些选项,用逗号隔开。如 fork,reuseaddr,stdin,stdout,ctty 等。

操作文件

例1、读取文件中数据到标准输出
注意相对路径记得要加上 ./

socat - ./temp.txt
socat - /root/temp.txt

例2、追加到文件
echo “test” | socat - ./temp.txt

端口监听与转发

socat - TCP:192.168.1.1:3306 连接远程端口

socat TCP-LISTEN:7000 - 监听一个 tcp 端口
socat udp-listen:23456 - 监听一个 UDP 端口

echo "test" | socat - tcp-connect:127.0.0.1:12345 向 TCP 端口发送数据
echo "test" | socat - udp-connect:127.0.0.1:23456 向一个 UDP 端口发送数据

端口转发

1、tcp 端口转发
nohup socat TCP4-LISTEN:80,reuseaddr,fork TCP4:1.1.1.1:80 >> socat.log 2>&1 &
监听 ipv4 的 80 端口,转发到 1.1.1.1 的 80 端口。
reuseaddr 设置本地端口可重复使用

2、udp 端口转发
nohup socat UDP4-LISTEN:10000,reuseaddr,fork UDP4:1.1.1.1:10000 >> socat.log 2>&1 &
监听 ipv4 的 10000 端口,转发到 1.1.1.1 的 10000 端口。

socat 将容器内端口暴露到宿主机

socat TCP-LISTEN:容器内端口,fork,reuseaddr TCP:容器ip:debug端口


tcpdump

tcpdump -i lo tcp port 8998 -xX 看下


Shell内建命令

sh

sh 命令是 shell 命令语言解释器,执行从标准输入或文件中读取的命令。

-c string 命令从 -c 后的字符串读取。
-i:实现脚本交互。
-n:进行shell脚本的语法检查。
-x:实现shell脚本逐条语句的跟踪。


env

set: 显示或设置 shell 变量, 包括用户环境变量和 shell 局部变量
env: 显示或设置环境变量, 只涉及当前用户的环境变量, 所以 env 看到的变量是 set 看到的变量的子集, 或者说 env 看到的变量个数小于等于 set 看到的变量个数
shell变量(set) = shell局部变量 + env环境变量
export: 显示当前导出成用户环境变量的 shell 变量,或将 shell 局部变量导出为用户环境变量

env PWD=/Dir 定义当前系统中的指定环境变量值


set

使用set更改shell特性时,符号 +- 的作用分别是打开和关闭指定的模式。
set命令不能够定义新的shell变量。如果要定义新的变量,可以使用declare命令以变量名=值的格式进行定义即可。

-b:使被中止的后台程序立刻回报执行状态。
-C:转向所产生的文件无法覆盖已存在的文件。
-d:Shell预设会用杂凑表记忆使用过的指令,以加速指令的执行。使用-d参数可取消。
-f:取消使用通配符。
-h:自动记录函数的所在位置。
-H Shell:可利用”!”加<指令编号>的方式来执行history中记录的指令。
-k:指令所给的参数都会被视为此指令的环境变量。
-l:记录for循环的变量名称。
-m:使用监视模式。
-n:只读取指令,而不实际执行。
-p:启动优先顺序模式。
-P:启动-P参数后,执行指令时,会以实际的文件或目录来取代符号连接。
-t:执行完随后的指令,即退出shell。
-v 显示shell所读取的输入值。

set -e 失败立即结束

-e: 若指令返回值不等于 0(即命令执行错误),则立即退出 shell。(默认情况下有命令执行失败也会继续往下执行, 即默认是关闭此选项的)
set +e 表示关闭-e选项
set -e 表示打开-e选项, 即有命令执行失败立即退出shell

一、脚本中有命令执行失败时立即结束
例如有脚本 tesh.sh

#! /bin/sh
set -ex
foo
pwd
ls -al

执行结果如下:

$ sh test.sh
+ foo
test.sh: line 4: foo: command not found

foo 命令找不到,执行失败,立即结束,不往后执行。

二、脚本中有命令执行失败时忽略继续往下执行
test.sh 在 foo 前 set +e 来关闭 -e 选项,之后再打开,表示期间的命令即使错误也继续执行

#! /bin/sh
set -x

set +e
foo
set -e

pwd
ls -al| head -n 2

执行结果如下:

$ sh test.sh
+ set +e
+ foo
test.sh: line 5: foo: command not found
+ set -e
+ pwd
/Users/si.ma
+ ls -al
+ head -n 2
total 86332176
drwxr-xr-x+ 84 si.ma  FAREAST\Domain Users         2688  9 25 13:10 .

还有一种方法是使用 command || true ,使得该命令即使执行失败,脚本也不会终止执行。

set -x 打印出命令本身

-x: 执行指令后, 会先输出该指令及其参数, 目的是为了解决 bash 脚本中有多条命令时分不清楚哪个输出是哪个命令产生的。

例如有如下脚本 test.sh

#! /bin/sh
set -x

foo
pwd
ls -al| head -n 2

执行结果如下:

$ sh test.sh
+ foo
test.sh: line 4: foo: command not found
+ pwd
/Users/si.ma
+ ls -al
+ head -n 2
total 85839768
drwxr-xr-x+ 84 si.ma  FAREAST\Domain Users         2688  9 25 13:05 .

输出每个命令的执行结果前会先打印出命令及参数。
管道连接的会被列为两个命令

set -u 遇到未定义变量时报错

-u: 当执行时使用到未定义过的变量,则显示错误信息。
默认情况下,执行脚本的时候,如果遇到不存在的变量,Bash 默认忽略它。


unset

unset 命令用于删除已定义的shell变量(包括环境变量)和shell函数。
注意set env export设置的变量,都可以用unset来清除的
unset命令不能够删除具有只读属性的shell变量和环境变量

-f:仅删除函数;
-v:仅删除变量。

清除环境变量的值用unset命令。如果未指定值,则该变量值将被 设为NULL。示
例如下:
$ export TEST="Test..." #增加一个环境变量TEST
$ env|grep TEST #此命令有输入,证明环境变量TEST已经存在了
TEST=Test...
$ unset $TEST #删除环境变量TEST
$ env|grep TEST #此命令没有输出,证明环境变量TEST已经不存在了

declare

declare 命令用于声明和显示已存在的shell变量。
declare命令若不带任何参数选项,则会显示所有shell变量及其值。
declare的功能与typeset命令的功能是相同的。

+/-:”-“可用来指定变量的属性,”+”则是取消变量所设的属性;
-f:仅显示函数;
r:将变量设置为只读;
-x:指定的变量会成为环境变量,可供shell以外的程序来使用;
+x:删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
i:[设置值]可以是数值,字符串或运算式。

declare命令用于声明 shell 变量。
declare name="masikkk"
也可以省略declare
name="masikkk"


export

export 命令显示当前导出成环境变量的 shell 变量,或将 shell 变量导出为环境变量。

一个shell中的 系统环境变量(用export定义的变量) 才会被复制到子 shell中

在子 shell中定义的变量只在该子shell内有效。如果在一个shell脚本程序中定义了一个变量,当该脚本程序运行时,这个定义的变量只是该脚本程序内 的一个局部变量,其他的shell不能引用它,要使某个变量的值可以在其他shell中被改变,可以使用export命令对已定义的变量进行输出。 export命令将使系统在创建每一个新的shell时定义这个变量的一个拷贝。这个过程称之为变量输出。

-f:代表[变量名称]中为函数名称;
-n:删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中;
-p:列出所有的shell赋予程序的环境变量。

export 命令的功能跟 declare 命令部分重合;
export name="masikkk" 相当于 declare -x name="masikkk"
export -n name 相当于 declare +x name


readonly

readonly 命令用于定义只读shell变量和shell函数。
readonly命令的选项-p可以输出显示系统中所有定义的只读变量。

-f:定义只读函数;
-a:定义只读数组变量;
-p:显示系统中全部只读变量列表。

使用了readonly命令的话,变量就不可以被修改或清除了。示例如下:

$ export TEST="Test..." #增加一个环境变量TEST
$ readonly TEST #将环境变量TEST设为只读
$ unset TEST #会发现此变量不能被删除
-bash: unset: TEST: cannot unset: readonly variable
$ TEST="New" #会发现此也变量不能被修改
-bash: TEST: readonly variable

echo

echo 命令用于在shell中打印shell变量的值,或者直接输出指定的字符串。linux的echo命令,在shell编程中极为常用。

-n 输出文字后不换行;

字符串能加引号,也能不加引号。
用echo命令输出加引号的字符串时,将字符串原样输出;
用echo命令输出不加引号的字符串时,将字符串中的各个单词作为字符串输出,各字符串之间用一个空格分割。

-e 激活转义字符。使用-e选项时,若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:
\a 发出警告声;
\b 删除前一个字符;
\c 不产生进一步输出 (\c 后面的字符不会输出);
\f 换行但光标仍旧停留在原来的位置;
\n 换行且光标移至行首;
\r 光标移至行首,但不换行;
\t 插入tab;
\v 与\f相同;
\ 插入\字符;
\nnn 插入 nnn(八进制)所代表的ASCII字符;

文字色
echo -e "\e[1;31mThis is red text\e[0m"
\e[1;31m 将颜色设置为红色
\e[0m 将颜色重新置回
颜色码:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37

背景色
echo -e "\e[1;42mGreed Background\e[0m"
颜色码:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47

文字闪动
echo -e "\033[37;31;5mMySQL Server Stop...\033[39;49;0m"
红色数字处还有其他数字参数:0 关闭所有属性、1 设置高亮度(加粗)、4 下划线、5 闪烁、7 反显、8 消隐


tput

tput 命令通过 terminfo 数据库对终端会话进行初始化和操作,可以更改几项终端功能,如移动或更改光标、更改文本属性,以及清除终端屏幕的特定区域。

1、修改文本属性
设置颜色

tput setab [0-7] – Set a background color using ANSI escape
tput setb [0-7] – Set a background color
tput setaf [0-7] – Set a foreground color using ANSI escape
tput setf [0-7] – Set a foreground color
0 – Black
1 – Red
2 – Green
3 – Yellow
4 – Blue
5 – Magenta
6 – Cyan
7 – White

例如
tput setaf 1 红色
tput setaf 2 绿色

其他文本属性

tput bold – Set bold mode 加粗
tput dim – turn on half-bright mode
tput smul – begin underline mode
tput rmul – exit underline mode
tput rev – Turn on reverse mode
tput smso – Enter standout mode (bold on rxvt)
tput rmso – Exit standout mode
tput sgr0 – Turn off all attributes 关闭所有属性修改

tput 命令行使用说明
https://blog.csdn.net/fdipzone/article/details/9993961


source

通常用法:source filepath. filepath
功能:使当前 shell 读入路径为 filepath 的 shell 文件并依次执行文件中的所有语句,通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。
例如,当我们修改了/etc/profile 文件,并想让它立刻生效,而不用重新登录,就可以使用 source 命令,如 source /etc/profile

source 命令(从 C Shell 而来)是 bash shell 的内置命令;点命令(.),就是个点符号(从Bourne Shell而来)是 source 的另一名称。这从用法中也能看出来。

source filepathsh filepath./filepath 的区别:

  • 当 shell 脚本具有可执行权限时,用 sh filepath 与 ./filepath 是没有区别的。./filepath 是因为当前目录没有在 PATH 中,所有 . 是用来表示当前目录的。
  • sh filepath 会重新建立一个子 shell,在子 shell 中执行脚本里面的语句,该子 shell 继承父 shell 的环境变量,但子 shell 是新建的,其改变的变量不会被带回父 shell,除非使用 export。
  • source filename 其实只是简单地读取脚本里面的语句依次在当前 shell 里面执行,没有建立新的子 shell。那么脚本里面所有新建、改变变量的语句都会保存在当前 shell 里面。

举例说明:
新建一个test.sh脚本,内容为:A=1;
修改其可执行权限:chmod +x test.sh;
运行sh test.sh后,echo $A,显示为空,因为A=1并未传回给当前shell;
运行./test.sh后,也是一样的效果;
运行source test.sh 或者 . test.sh,然后echo $A,则会显示1,说明A=1的变量在当前shell中;


exec

exec 命令用于调用并执行指令。
exec 并不启动新的 shell,而是用要被执行命令替换当前的 shell 进程,并且将老进程的环境清理掉,且执行完命令后进程也就结束了。
所以,exec 命令通常用在 shell 脚本程序中,可以调用其他的命令。如果在当前终端中使用命令,则当指定的命令执行完毕后会立即退出终端。


command

command 调用并执行指定的命令,且忽略 shell 的函数
如果有一个命令和一个函数同名,正常执行这个命令时,shell 会优先执行函数。但是如果你使用 command 命令,shell 就会忽略函数,直接执行命令。

command -v 检查命令是否存在

command -v 搜索命令信息但是不执行,如果命令存在则返回命令

# command -v ls
alias ls='ls --color=auto'
# command -v mv
alias mv='mv -i'
# command -v netstat
/usr/bin/netstat

command -v 可用于检查系统是否安装了某个命令,例如执行 command -v htop,如果没安装 htop 就没有返回结果
下面的脚本,使用 command -v 检查 htop 命令是否存在,有则执行 htop,否则执行 top

#!/bin/bash
if command -v htop >/dev/null; then
    htop
else
    top
fi

eval

eval 用于执行命令和表达式求值。
eval 命令通常用于在命令的参数中包含 shell 命令。eval 会先进行一次 shell 扩展(变量替换、命令替换等),然后再执行生成的命令。


shopt

shopt(shell options) 不是 linux POSIX 标准命令,而是 bash 这个特定 shell 的内建命令。 在 zsh 中是没有 shopt 命令的。
命令用于显示和设置 shell 中的行为选项,通过这些选项以增强 shell 易用性。
shopt 命令若不带任何参数选项,则可以显示所有可以设置的 shell 操作选项。

-s 激活指定的shell行为选项;
-u 关闭指定的shell行为选项。

shopt 显示所有可配置的选项及其状态
shopt -s opt_name 启用(set) opt_name 选项
shopt -u opt_name 禁用(unset) opt_name 选项
shopt opt_name 查看 opt_name 选项的当前状态

zsh中没有shopt命令

command not found: shopt
使用 Mac 时多数人都会将命令行切换为 zsh, 但 zsh 中是没有 shopt 命令的,有时候一些工具安装脚本中有 shopt 命令就会报错。

解决:
可以临时切换为 bash 命令行运行脚本。
其实


alias

alias 命令用来设置指令的别名。我们可以使用该命令可以将一些较长的命令进行简化。使用 alias 时,用户必须使用单引号’’将原来的命令引起来,防止特殊字符导致错误。
alias 命令的作用只局限于该次登入的操作。若要每次登入都能够使用这些命令别名,则可将相应的 alias 命令存放到 bash 的初始化文件 /etc/bashrc 中。

alias命令格式:
alias 新的命令='原命令 -选项/参数'
要删除一个别名,可以使用 unalias 命令,如 unalias l

alias 不加任何参数,列出已经设置的别名。

在shell脚本中使用alias

Linux shell 有交互式与非交互式两种工作模式。我们日常使用 shell 输入命令得到结果的方式是交互式的方式,而 shell 脚本使用的是非交互式方式。

shell 提供了 alias 功能来简化我们的日常操作,使得我们可以为一个复杂的命令取一个简单的名字。在交互式模式下,shell 的 alias 扩展功能是打开的,因此我们可以键入自己定义的 alias 别名来执行对应的命令。

但是,在非交互式模式下 alias 扩展功能默认是关闭的,此时仍然可以定义 alias 别名,但是 shell 不会将 alias 别名扩展成对应的命令,而是将 alias 别名本身当作命令执行,如果 shell 内置命令和 PATH 中均没有与 alias 别名同名的命令,则 shell 会“抱怨”找不到指定的命令。

如何在 shell 脚本中也可以使用 alias 别名呢?
可以使用 shell 内置命令 shopt 命令来开启 alias 扩展选项。shopt 是 shell 的内置命令,可以控制 shell 功能选项的开启和关闭,从而控制 shell 的行为。
alias 扩展功能的选项名称是 expand_aliases 在交互式模式下此选项是默认开启

# shopt expand_aliases
expand_aliases     on

在非交互式模式下 alias 扩展功能 expand_aliases 默认是关闭的,但是我们可以用 shopt 来将其开启

shopt -s expand_aliases

history

history 命令用于显示历史命令,读取历史命令文件中的目录到历史命令缓冲区和将历史命令缓冲区中的目录写入命令文件。

-c:清空当前历史命令;
-a:将历史命令缓冲区中命令写入历史命令文件中;
-r:将历史命令文件中的命令读入当前历史命令缓冲区;
-w:将当前历史命令缓冲区命令写入历史命令文件中。
历史命令是被保存在内存中的,当退出或者登录shell时,会自动保存或读取。在内存中,历史命令仅能够存储1000条历史命令,该数量是由环境变量HISTSIZE进行控制。

该命令单独使用时,仅显示历史命令
history 10,显示最近使用的10条历史命令

在命令行中,可以使用符号!执行指定序号的历史命令。
!2,执行第2个历史命令。
!!,执行上一条命令。
!-1,执行上一条命令。

history个数设置(上下方向键无法查看历史记录)

$HISTSIZE 环境变量控制 history 记录条数。
如果 echo $HISTSIZE 结果为0,说明 history 命令被禁用了,上下方向键也就无法查看命令历史记录。

1、临时修改:
设置 HISTSIZE 环境变量为非0值,执行 export HISTSIZE=500

2、永久修改:
编辑 /etc/profile 添加
HISTSIZE=500
export HISTSIZE
执行 source /etc/profile 使环境变量生效

history命令显示时间

注意:运行了一段时间的服务器新增 history 时间参数的话,之前命令的时间会被初始化为当前时间点

1、设置 HISTTIMEFORMAT 环境变量可以让 history 命令记录时间,其时间格式描述和date命令是一致的。
export HISTTIMEFORMAT="%F %T "
下次再登录时history就会恢复默认设置,这只是一种临时显示的方法。

2、要想永久生效,可以编辑 /etc/bashrc,在最后增加

HISTTIMEFORMAT="%F %T "
export HISTTIMEFORMAT

退出后重新登录。


kill

kill命令用来删除执行中的程序或工作。kill可将指定的信息送至程序。预设的信息为SIGTERM(15),可将指定程序终止。若仍无法终止该程序,可使用SIGKILL(9)信息尝试强制删除程序。程序或工作的编号可利用ps指令或job指令查看。

kill [参数] [进程号]

SIGTERM(-15)默认信号可被处理

默认(缺省)情况下,kill 发送的是 SIGTERM,即 15(SIGTERM) 信号,kill PIDkill -15 PID 是一样的。
这个信号通常会要求程序自己正常退出,是一种比较安全的用法。但它是可以被阻塞,处理和忽略的,所以对于有的进程,会中止失败。

SIGKILL(-9)立即结束

另一个常用的信号是9(SIGKILL),这个命令表示立即结束程序,是不能被阻塞,处理和忽略的。在TERM信号失效的情况下,可以尝试使用 kill -9 PID
事实上,SIGKILL 信号是直接发给init进程的,它收到该信号后,负责终止pid指定的进程。

虽然”kill -9”命令已经很强大,但也有可能还是不能达到目的。这时候,还有一个办法,就是使用”ps -ef”找出待中止的进程的父进程(PPID),然后使用kill或killall命令杀掉它。

SIGINT(-2)等于Ctrl+C

kill -2 pid 功能类似于Ctrl + C 是程序在结束之前,能够保存相关数据,然后再退出。

常用信号名称

kill -l 查看全部信号及对应数字

SIGHUP 1 挂起进程
SIGINT 2 中断(同 Ctrl + C)
SIGQUIT 3 退出(同 Ctrl + \)
SIGKILL 9 强制终止,不能被忽略、处理和阻塞
SIGTERM 15 尽可能终止进程,可被处理
SIGCHLD 17 子进程退出(子进程发给父进程的信号),默认忽略
SIGCONT 18 继续运行停止的进程
SIGSTOP 19 暂停(同 Ctrl + Z),不能被忽略、处理和阻塞

批量kill -9

ps -ef|grep 'nginx:'|awk '{print $2}'|xargs kill -9

僵尸进程(defunct)

linux 僵尸进程是一个已经终止,但是其父进程尚未对其进行善后处理获取终止进程的有关信息的进程;
僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。

僵尸进程是如何产生的?
Linux 允许进程查询内核以获得其父进程的 PID,或者其任何子进程的执行状态。例如,进程可以创建一个子进程来执行特定的任务,然后调用诸如 wait() 这样的一些库函数检查子进程是否终止。如果子进程已经终止,那么,它的终止代号将告诉父进程这个任务是否已成功地完成。
为了遵循这些设计原则,不允许 Linux 内核在进程一终止后就丢弃包含在进程描述符字段中的数据。只有父进程发出了与被终止的进程相关的 wait() 类系统调用之后,才允许这样做。这就是引入僵死状态的原因:尽管从技术上来说进程已死,但必须保存它的描述符,直到父进程得到通知。
在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程。
僵尸进程是一个早已死亡的进程,但在进程表 (processs table)中仍占了一个位置(slot)。

僵尸进程的危害?
在进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号 PID,退出状态 the termination status of the process,运行时间 the amount of CPU time taken by the process 等)。直到父进程通过 wait / waitpid 来取时才释放。
如果进程不调用 wait / waitpid 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。

如何查找僵尸进程?
1、ps -aux 结果的 stat 里,僵尸进程的状态是 Z

# ps -aux|grep " Z"
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     61908  0.0  0.0      0     0 ?        Z    Aug10   0:00 [yum] <defunct>
root     76390  0.0  0.0      0     0 ?        Z    Aug10   0:00 [yum] <defunct>

2、ps -ef 结果的 cmd 里,僵尸进程带有 defunct 标识

ps -ef|grep defunct
UID        PID  PPID  C STIME TTY          TIME CMD
root     61908 75206  0 Aug10 ?        00:00:00 [yum] <defunct>
root     76390 75206  0 Aug10 ?        00:00:00 [yum] <defunct>
root     82300 75206  0 Aug10 ?        00:00:00 [yum] <defunct>

利用命令ps,可以看到有父进程ID为1的进程是孤儿进程;s(state)状态为Z的是僵尸进程。
孤儿进程(orphan process)是尚未终止但已停止(相当于前台挂起)的进程,但其父进程已经终止,由init收养;而僵尸进程则是已终止的进程,其父进程不一定终止。

如何清除僵尸进程?
把父进程杀掉。父进程死后,僵尸进程成为”孤儿进程”,过继给1号进程init,init始终会负责清理僵尸进程,关机或重启后所有僵尸进程都会消失。
子进程死后, 会发送 SIGCHLD 信号给父进程,父进程收到此信号后,执行 waitpid()函数为子进程收尸。

pkill

pkill -u admin 杀掉用户 admin 的所有进程

killall

killall pname 杀掉 pname 相关的进程
killall -u admin 删掉用户 admin 的所有进程


trap

捕捉信号和其他事件并执行命令
trap 'commands' signals 收到 signals 信号时执行 commands 命令
trap '' signals 如果命令为空字符串,则指定的信号会被忽略
trap signals 不指定命令,收到 signals 信号时默认操作是结束进程
commands 接收到信号时执行的命令,
signals 信号名称或信号名称对应的数字,可以是多个

例1、忽略一个或多个信号
trap ‘’ 2
trap ‘’ 1 2 3 15

例2、当 shell 收到 HUP INT PIPE QUIT TERM 这几个命令时,当前执行的程序会执行 exit 1
trap “exit 1” HUP INT PIPE QUIT TERM

例3、有人试图从终端中止程序时删除文件再退出
trap “rm -f $WORKDIR/work1 $WORKDIR/dataout; exit” 2


wait

wait 是用来阻塞当前进程的执行,直至指定的子进程执行结束后,才继续执行。
使用 wait 可以在 bash 脚本“多进程”执行模式下,起到一些特殊控制的作用。
该指令常用于 shell 脚本编程中,待指定的指令执行完成后,才会继续执行后面的任务。

wait [options] ID
options 选项,可选参数
ID 是进程或作业ID。作业ID前必须添加百分号”%”。
如果没有指定ID,wait命令等待所有进程状态改变。并返回的最后一个进程的退出状态。

例1、wait 7654
等待PID 7654的后台进程直到退出。当指定多个进程时,wait命令等待所有进程状态改变。

例2、wait %1
等待作业号为1的作业完成

例3、等待所有子进程执行完后继续

#!/bin/sh
echo “1”
sleep 5&
echo “3”
echo “4”
wait  #会等待wait所在bash上的所有子进程的执行结束,本例中就是sleep 5这句
echo”5”

ulimit

ulimit 命令用来限制系统用户对 shell 资源的访问。

ulimit 用于限制 shell 启动进程所占用的资源,支持以下各种类型的限制:所创建的内核文件的大小、进程数据块的大小、Shell 进程创建文件的大小、内存锁住的大小、常驻内存集的大小、打开文件描述符的数量、分配堆栈的最大大小、CPU 时间、单个用户的最大线程数、Shell 进程所能使用的最大虚拟内存。同时,它支持硬资源和软资源的限制。

作为临时限制,ulimit 可以作用于通过使用其命令登录的 shell 会话,在会话终止时便结束限制,并不影响于其他 shell 会话。
而对于长期的固定限制,ulimit 命令语句又可以被添加到由登录 shell 读取的文件中,作用于特定的 shell 用户。

1)暂时生效,使用ulimit命令设置,适用于通过 ulimit 命令登录 shell 会话期间
2)永久生效,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件之一(例如 ~/.profile),即特定于 shell 的用户资源文件;或者通过编辑 /etc/security/limits.conf

-a:显示目前资源限制的设定;
-c :设定core文件的最大值,单位为区块;
-d <数据节区大小>:程序数据节区的最大值,单位为KB;
-f <文件大小>:shell所能建立的最大文件,单位为区块;
-H:设定资源的硬性限制,也就是管理员所设下的限制;
-m <内存大小>:指定可使用内存的上限,单位为KB;
-n <文件数目>:指定同一时间最多可开启的文件数; 对于需要做许多套接字连接并使它们处于打开状态的应用程序而言,最好通过使用ulimit -n,或者通过设置nofile参数,为用户把文件描述符的数量设置得比默认值高一些。
-p <缓冲区大小>:指定管道缓冲区的大小,单位512字节;
-s <堆叠大小>:指定堆叠的上限,单位为KB;
-S:设定资源的弹性限制;
-t :指定CPU使用时间的上限,单位为秒;
-u <程序数目>:用户最多可开启的程序数目;
-v <虚拟内存大小>:指定可使用的虚拟内存上限,单位为KB。

ulimit -a 查看所有 shell 资源限制值

ulimit -c unlimited 将core文件的大小设为无限

ulimit -n 4096 限制用户的最大文件打开数为4096个


内核与模块管理

sysctl

sysctl 命令被用于在内核运行时动态地修改内核的运行参数
可用的内核参数在目录 /proc/sys 中。它包含一些 TCP/IP 堆栈和虚拟内存系统的高级选项,用 sysctl 可以读取设置超过五百个系统变量。
/proc/sys 中的内核参数在系统运行的同时可以进行更改,不过重新启动机器后会失效,可以通过更改 /proc/sys 中内核参数对应的文件 /etc/sysctl.conf 的内核参数来永久更改。

-n:打印值时不打印关键字;
-e:忽略未知关键字错误;
-N:仅打印名称;
-w:当改变sysctl设置时使用此项;
-p, --load[=<file>] 从指定的配置文件加载内核参数设置
-a, --all 打印当前所有可用的内核参数变量和值;
-A:以表格方式打印当前所有可用的内核参数变量和值。

-p[FILE], --load[=FILE] 从指定文件(默认 /etc/sysctl.conf )中加载已经设置好的一系列变量值。
如果使用 - 作为文件名,那么表示从 stdin 读取配置。
FILE 还可以是一个正则表达式,以匹配多个文件。

--system 从所有下列配置文件中加载系统设置
/run/sysctl.d/.conf
/etc/sysctl.d/
.conf
/usr/local/lib/sysctl.d/.conf
/usr/lib/sysctl.d/
.conf
/lib/sysctl.d/*.conf
/etc/sysctl.conf

sysctl -a 查看所有可读变量
sysctl key 查看指定变量
例如查看 tcp keepalive 的内核参数

$ sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_probes net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

net.ipv4.tcp_keepalive_time 是连接时长,当超过这个时间后,每隔 net.ipv4.tcp_keepalive_intvl 的时间间隔会发送keepalive数据包,net.ipv4.tcp_keepalive_probe 是发送keepalived数据包的频率。

sysctl key=value 设置变量值
例如 sysctl kern.maxfiles=5000

sudo sysctl --system 从所有系统目录读取配置参数值

sysctl 中文手册
http://www.jinbuguo.com/man/sysctl.html

修改linux内核参数的3种方式

修改 linux 内核参数有 3 种方式:
1、修改 /etc/sysctl.conf 文件,加入配置选项,格式为 key = value ,修改保存后调用 sysctl -p 加载新配置
2、使用 sysctl 命令临时修改,重启后会失效
3、直接修改 /proc/sys/ 目录中的文件,如: echo “379008 505344 758016” > /proc/sys/net/ipv4/tcp_mem
第一种方式在操作系统重启后会自动生效,第二和第三种方法重启后失效

systemd-sysctl.service

systemd-sysctl.service 服务 在系统启动的早期 通过调用 /usr/lib/systemd/systemd-sysctl 工具配置 sysctl 内核参数。
如果不使用任何参数调用 /usr/lib/systemd/systemd-sysctl 命令, 那么将应用 sysctl.d 目录下所有配置文件中的指令。 如果明确指定了一个或多个文件名, 那么将仅应用指定的配置文件中的指令。
此外,可以使用 –prefix= 选项来仅应用 某些特定前缀的 sysctl 内核参数。

systemd-sysctl.service 中文手册
http://www.jinbuguo.com/systemd/systemd-sysctl.service.html

sysctl.d内核参数配置文件目录

systemd-sysctl.service 服务在系统启动时会读取下面几个目录中的 *.conf 配置文件来设置linux内核参数
/etc/sysctl.d/.conf
/run/sysctl.d/
.conf
/usr/lib/sysctl.d/*.conf
配置文件的格式是 一系列”KEY=VALUE”行(每行一对)。 空行以及以 “#” 或 “;” 开头的行都将被忽略。

sysctl.d/ 中的设置将在系统启动的早期被应用。 针对网络接口的配置, 则会在对应的网络接口出现的时候被应用。

许多 sysctl 参数仅在加载相应的内核模块之后才可用。 因为内核模块是按需动态加载的 (例如在插入新硬件或启动网络时), 所以在系统启动早期运行的 systemd-sysctl.service 无法设置那些依赖于特定内核模块的参数。 对于这些参数, 首选的方法是通过 udev 规则来设置, 次选的方法是将这些模块添加到 modules-load.d 中, 因为 modules-load.d 中的模块会在运行 systemd-sysctl.service 前被无条件的静态加载(参见”例子”小节)。

目录及配置文件优先级
配置文件依次从 /etc/, /run/, /usr/lib/ 目录中读取。
配置文件的名称必须符合 filename.conf 格式。 对于不同目录下的同名配置文件,仅以优先级最高的目录中的那一个为准。 具体说来就是: /etc/ 的优先级最高、 /run/ 的优先级居中、 /usr/lib/ 的优先级最低。

软件包应该将自带的配置文件安装在 /usr/lib/ 目录中。 /etc/ 目录仅供系统管理员使用。 所有的配置文件(无论位于哪个目录中), 统一按照文件名的字典顺序处理。 如果在多个配置文件中设置了同一个选项, 那么仅以文件名最靠后(字典顺序)的那一个为准。 为了便于排序,建议给所有配置文件 都加上两位十进制数字的文件名前缀。

如果系统管理员想要屏蔽 /usr/lib/ 目录中的某个配置文件, 那么最佳做法是在 /etc/ 目录中 创建一个指向 /dev/null 的同名符号链接, 即可彻底屏蔽 /usr/lib/ 目录中的同名文件。 如果软件包自带的某个配置文件位于 initrd 镜像中, 那么还必须重新生成 initrd 镜像。

sysctl.d 中文手册
http://www.jinbuguo.com/systemd/sysctl.d.html


lsmod

lsmod 命令用于显示已经加载到内核中的模块的状态信息。
执行lsmod命令后会列出所有已载入系统的模块。Linux操作系统的核心具有模块化的特性,应此在编译核心时,无须把全部的功能都放入核心。您可以将这些功能编译成一个个单独的模块,待需要时再分别载入。

第1列:表示模块的名称。
第2列:表示模块的大小,单位字节。
第3列:表示此模块被多少个其他模块所依赖。
第4列:列出依赖此模块的其他模块。

$ lsmod
Module                  Size  Used by
veth                   13410  0
xt_conntrack           12760  1
ipt_MASQUERADE         12678  1
nf_nat_masquerade_ipv4    13412  1 ipt_MASQUERADE
nf_conntrack_netlink    36354  0
nfnetlink              14490  2 nf_conntrack_netlink
xt_addrtype            12676  2
iptable_filter         12810  1
iptable_nat            12875  1

判断模块是否已加载到内核

lsmod 命令经常配合 grep 判断某个内核模块是否加载,比如判断 br_netfilter 模块是否加载 lsmod | grep br_netfilter 有结果就是已加载

modprobe

modprobe 命令 用于智能地向内核中加载模块或者从内核中移除模块。
modprobe 可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。

sudo modprobe br_netfilter 加载 br_netfilter 模块
modprobe -r 模块名 移除已加载的模块


uname

uname 是 unix name 的缩写
uname -a 显示操作系统相关所有参数

查看Linux内核版本

1、uname -a 查看 linux 内核版本

$ uname -a
Linux lightsail 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

2、通过查看 /proc/version 文件确认内核版本。uname -a 的结果就是从这个文件中获取的。

$ cat /proc/version
Linux version 3.10.0-957.1.3.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Thu Nov 29 14:49:43 UTC 2018

查看Linux系统版本

一般在 /etc/ 目录下都有个 -version-release 结尾的文件,里面写有操作系统的版本信息

查看CentOS系统版本

CentOS 5.x 是 /etc/redhat-release 文件,cat查看 CentOS release 5.11 (Final)
CentOS 6.x 及以上是 /etc/centos-release 文件,redhat-release 文件也还在,两个文件内容一样,都是 centos 版本
CentOS 7.x 可直接查看 /etc/os-release 文件,当然也保留了 /etc/redhat-release/etc/centos-release
CentOS 7.x 中,虽然 redhat-release/centos-release/system-release 中都是简化版本信息,但是要想看 CentOS 是 7.3 还是 7.6, 只能在这三个文件中看到。

$ cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
$ cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
$ cat /etc/system-release
CentOS Linux release 7.6.1810 (Core)
查看RedHat系统版本

查看 /etc/redhat-release 文件
Red Hat Enterprise Linux Server release 6.3 (Santiago)

查看Alpine系统版本

查看 /etc/os-release 文件

# cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.10.4
PRETTY_NAME="Alpine Linux v3.10"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"

还有个 /etc/alpine-release 里面是简化版本信息

# cat /etc/alpine-release
3.10.4
查看Debian系统版本

查看 /etc/os-release 文件

# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
root@centos:/# cat /etc/timezone
Etc/UTC
root@centos:/# env|grep TZ
TZ=Asia/Shanghai
root@centos:/# date
Thu Dec 26 12:06:33 CST 2019

dmesg 查看内核日志

dmesg(display message) 命令用于显示内核相关信息

kernel 会将内核相关信息存储在内核环缓冲区(kernel-ring buffer) 中,可通过 dmesg 命令查看,也可直接查看 /var/log/dmesg 文件。

dmesg 命令是从内核环形缓冲区中获取数据的。当我们在 Linux 上排除故障时,dmesg 命令会十分方便,它能很好地帮我们鉴别硬件相关的error和warning。除此之外,dmesg命令还能打印出守护进程相关的信息,已帮助我们debug。

-T 显示易读的时间戳格式
dmesg -T


journalctl 查看服务日志

journalctl 用来查询 systemd-journald 服务(systemd-journald.service)收集到的日志。systemd-journald 服务是 systemd 系统提供的收集系统日志的服务。
Systemd 统一管理所有 Unit 的启动日志,可以只用 journalctl 一个命令查看所有日志(内核日志和应用日志)。
journalctl 工具是 CentOS7 才有的工具

journalctl 的内容来自系统日志,ubuntu 的系统日志在 /var/log/syslog,centos 的系统日志在 /var/log/messages
默认情况下 systemd-journald 服务只保存本次启动后的日志(重新启动后丢掉以前的日志)

-b 查看系统本次启动后的日志
-k 查看内核日志,-k 选项是通过 -b 选项加上匹配条件 “_TRANSPORT=kernel” 实现的
-n 指定日志条数

-x --catalog 在日志的输出中 增加一些解释性的短文本, 以帮助进一步说明 日志的含义、 问题的解决方案、支持论坛、 开发文档、以及其他任何内容。 并非所有日志都有 这些额外的帮助文本
-e --pager-end 在分页工具内 立即跳转到日志的尾部。 此选项隐含了 -n1000 以确保分页工具不必缓存太多的日志行。 不过这个隐含的行数可以被明确设置的 -n 选项覆盖。
-f --follow 只显示最新的日志项, 并且不断显示新生成的日志项。 此选项隐含了 -n 选项。
-u --unit=UNIT 查看指定服务的日志。仅显示 属于特定单元的日志。 也就是单元名称正好等于 UNIT 或者符合 PATTERN 模式的单元。 这相当于添加了一个 “_SYSTEMD_UNIT=UNIT” 匹配项(对于 UNIT 来说), 或一组匹配项(对于 PATTERN 来说)。

journalctl 查看所有日志(默认情况下 ,只保存本次启动的日志)如果不带任何参数直接调用此命令, 那么将显示所有日志内容 (从最早一条日志记录开始)。
journalctl -n 20 查看最近发生的20条日志
journalctl -xef 输出最近1000条日志,并滚动输出最新日志
journalctl -u httpd 查看httpd服务的日志信息

sudo journalctl -xefu kubelet 查看 kubelet 的启动错误日志。

限定日志所能占用的最高容量

可以通过 /etc/systemd/journald.conf 文件来配置 systemd-journald 服务的行为。以下条目可用于限定日志数据可以占用的最大存储数量和日志数据体积的膨胀速度:
SystemMaxUse=:指定journal所能使用的最高持久存储容量。
SystemKeepFree=:指定journal在添加新条目时需要保留的剩余空间。
SystemMaxFileSize=:控制单一journal文件大小,符合要求方可被转为持久存储。
RuntimeMaxUse=:指定易失性存储中的最大可用磁盘容量(/run文件系统之内)。
RuntimeKeepFree=:指定向易失性存储内写入数据时为其它应用保留的空间量(/run文件系统之内)。
RuntimeMaxFileSize=:指定单一journal文件可占用的最大易失性存储容量(/run文件系统之内)。
通过设置上述值,可以控制 systemd-journald 服务对服务器空间的消耗及保留方式。

查看进程被谁kill了

dmesg | egrep -i -B100 'killed process'

或:
egrep -i 'killed process' /var/log/messages
egrep -i -r 'killed process' /var/log

或:
journalctl -xb | egrep -i 'killed process'

# journalctl -xb | egrep -i 'killed process'
Oct 23 22:56:39 centos kernel: Killed process 19326 (java) total-vm:42501688kB, anon-rss:4152696kB, file-rss:4044kB, shmem-rss:0kB
Oct 24 18:57:06 centos kernel: Killed process 48484 (mongod) total-vm:71151988kB, anon-rss:70203076kB, file-rss:0kB, shmem-rss:0kB
Oct 25 03:30:26 centos kernel: Killed process 63385 (ass-server) total-vm:60901276kB, anon-rss:54418832kB, file-rss:80kB, shmem-rss:0kB

我的进程去哪儿了,谁杀了我的进程
https://www.cnblogs.com/xybaby/p/8098229.html

What killed my process and why?
https://stackoverflow.com/questions/726690/what-killed-my-process-and-why


文件系统与磁盘

sync

在 Linux/Unix 系统中,在文件或数据处理过程中一般先放到内存缓冲区中,等到适当的时候再写入磁盘,以提高系统的运行效率。
sync 命令则可用来强制将内存缓冲区中的数据立即写入磁盘中。用户通常不需执行 sync 命令,系统会自动执行 update 或 bdflush 操作,将缓冲区的数据写入磁盘。只有在 update 或 bdflush 无法执行或用户需要非正常关机时,才需手动执行sync命令。

linux系统为了提高读写磁盘的效率,会先将数据放在一块buffer中。在写磁盘时并不是立即将数据写到磁盘中,而是先写入这块buffer中了。此时如果重启系统,就可能造成数据丢失。

sync命令用来flush文件系统buffer,这样数据才会真正的写到磁盘中,并且buffer才能够释放出来,flush就是用来清空buffer。sync命令会强制将数据写入磁盘中,并释放该数据对应的buffer,所以常常会在写磁盘后输入sync命令来将数据真正的写入磁盘。

如果不去手动的输入sync命令来真正的去写磁盘,linux系统也会周期性的去sync数据。

swapon

swapon 命令用于激活Linux系统中交换空间,Linux系统的内存管理必须使用交换区来建立虚拟内存。

-a:将/etc/fstab文件中所有设置为swap的设备,启动为交换区;
-h:显示帮助;
-p<优先顺序>:指定交换区的优先顺序;
-s:显示交换区的使用状况;
-V:显示版本信息。

swapon -s 查看系统交换空间使用状况:

$ swapon -s
文件名             类型      大小    已用   权限
/dev/nvme0n1p2  partition    839676    227688    -1

其实 swapon -s 命令查看的是 /proc/swaps 文件的内容,等价于:
cat /proc/swaps

$ cat /proc/swaps
Filename                Type        Size    Used    Priority
/swapfile1                              file        1048572    142592    -2

如果配置有多个swap分区或者文件的话,这里将会有多行,每行代表一个正在被系统使用的swap分区或文件,下面是每个字段的意思:
Filename:如果swap类型是分区,这里将是分区的路径,如果swap类型是文件,这里将是文件的路径
Type:swap的类型,partition代表这是一个swap分区,file代表这是一个swap文件
Size:swap的大小,单位是k
Used:已经被使用的大小
Priority:优先级,优先级高的swap将会被优先使用,同等优先级的swap将会被均匀的使用(round-robin算法),优先级可以通过“swapon -p”命令来设置

swapoff

swapoff 命令用于关闭指定的交换空间(包括交换文件和交换分区)。
swapoff 实际上为 swapon 的符号连接,可用来关闭系统的交换区。
swapoff [-a] 交换空间或交换分区
-a:关闭配置文件“/etc/fstab”中所有的交换空间。

swapoff /dev/sda2 关闭 /dev/sda2 交换分区

swapoff -a 关闭配置文件“/etc/fstab”中所有的交换空间


mkswap

mkswap命令用于在一个文件或者设备上建立交换分区。在建立完之后要使用sawpon命令开始使用这个交换区。

添加交换分区

添加一个交换分区,步骤如下:
使用fdisk来创建交换分区(假设 /dev/sdb2 是创建的交换分区)
使用 mkswap 命令来设置交换分区:
mkswap /dev/sdb2
注意:指定分区上的所有数据会丢失。

启用交换分区:
swapon /dev/sdb2

写入/etc/fstab,以便在系统启动时自动加载交换分区:
/dev/sdb2 none swap defaults 0 0

添加交换文件

添加一个交换文件,步骤如下:
创建大小为512MB的交换文件:
dd if=/dev/zero of=/swapfile1 bs=1M count=512

修改文件的权限,避免其他用户对这个文件进行误操作:
chmod 600 /swapfile1

使用mkswap命令来设置交换文件:
mkswap /swapfile1

启用交换文件:
swapon /swapfile1

写入/etc/fstab,以便在系统启动时自动加载交换文件:
/swapfile1 none swap defaults 0 0

新添了交换分区并启用它之后,请查看 cat /proc/swapsfreeswapon -s 命令的输出来确保交换分区已被启用了。

删除交换文件

如果要删除一个交换文件,必须先停用它。
作为root运行:
swapoff -a
-a 即关闭配置文件“/etc/fstab”中所有的交换空间。

然后即可删除它:
rm -rf /swapfile

当然我们还需要修改 /etc/fstab,否则下次重启后,系统又会重新挂载相应的swap分区和文件
最后从 /etc/fstab 中删除相关条目


du

du 命令作用是估计文件系统的磁盘已使用量,常用于查看文件或目录所占磁盘容量。
在默认情况下,输出结果大小是以 KB 为单位的。如果想以 MB 为单位,使用 -m 参数即可,如果只想知道目录占了多少容量,使用 -s 参数即可。

-m--block-size=1m 以MB为单位
-h, --human-readable 以K,M,G为单位,提高信息的可读性。默认以 KB 为单位。
-d, --max-depth=N 指定目录深度。如果 --max-depth=0 就相当于 -s 参数,只统计总量而已。如果 --max-depth=1 就相当于 du -s 目录/*
-s, --summarize 仅列出总量,而不列出每个目录和文件的大小

du -sh * 当前目录下文件和目录大小

du -sh * 显示当前目录下的子目录和文件大小。-h表示易读,-s表示只统计总量,* 匹配当前目录下的所有子目录和文件,但是不包括隐藏文件/夹
du -sh * .[^.]* 显示所有文件/夹的大小,包括隐藏文件/夹
du -h --max-depth=1:输出当前目录下各个子目录所使用的空间,等于 du -hd 1
du -sh /home/* 显示 /home/ 目录下的所有子目录和文件大小

查看磁盘占用 10G 以上的目录
du -sh *|egrep "[0-9]{2,}G"

df

检查文件系统的磁盘空间占用情况,默认情况下,磁盘空间将以 1KB 为单位进行显示
-h, --human-readable 以更易读的方式呈现
df -i 查看每个硬盘分区的inode总数和已经使用的数量

执行 for i in /*; do echo $i; find $i | wc -l; done 查看各个文件夹的文件数,删除。
执行 for i in ./*; do echo $i; find $i | wc -l; done 查看当前文件夹下的文件数

IUsed 是每个挂载点的 inode 个数,即文件个数。

# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/sda2         12M  293K   12M    3% /
devtmpfs          32M   551   32M    1% /dev
tmpfs             32M     4   32M    1% /dev/shm
tmpfs             32M  1.1K   32M    1% /run
tmpfs             32M    16   32M    1% /sys/fs/cgroup
none              32M    48   32M    1% /noah/download
none              32M  6.3K   32M    1% /noah/modules
none              32M   182   32M    1% /noah/tmp
none              32M    35   32M    1% /noah/bin
/dev/loop0          0     0     0     - /mnt/cdrom
/dev/sdb1        466M  331K  466M    1% /data
tmpfs             32M     1   32M    1% /run/user/0
/dev/sda3        101M  3.3M   97M    4% /home
overlay          466M  331K  466M    1% /data/docker/overlay2/c8799caf73939ed378c1efe74e62add072bc0246a764fbcf7c0216b98efd6033/merged
overlay          466M  331K  466M    1% /data/docker/overlay2/91c7f622b2a3ed30ef1f73e09007acce37909e3bcbd99ce109d30cb041884e9a/merged
overlay          466M  331K  466M    1% /data/docker/overlay2/8792066bd17fbe5a384613e697729295d54bdfba4f9390da3f06cc83f449068a/merged
overlay          466M  331K  466M    1% /data/docker/overlay2/8697a1eb2cba0402314fc3b3b49d389bbbe08c501ef0acde25360cecb2bb7c88/merged
overlay          466M  331K  466M    1% /data/docker/overlay2/98cde434cedb5ce5085fc4862f3cef1ecaf735a3f32ad7425a4b3e5d0bfb8e35/merged
tmpfs             32M     1   32M    1% /run/user/1009

lsblk

lsblk 命令用于列出所有可用块设备的信息,而且还能显示他们之间的依赖关系,但是它不会列出 RAM 盘的信息。
块设备有硬盘,闪存盘,cd-ROM 等等。

-a, –all 显示所有设备。
-b, –bytes 以bytes方式显示设备大小。
-d, –nodeps 不显示 slaves 或 holders。
-D, –discard print discard capabilities。
-e, –exclude 排除设备 (default: RAM disks)。
-f, –fs 显示文件系统信息。
-h, –help 显示帮助信息。
-i, –ascii use ascii characters only。
-m, –perms 显示权限信息。
-l, –list 使用列表格式显示。
-n, –noheadings 不显示标题。
-o, –output 输出列。
-P, –pairs 使用key=”value”格式显示。
-r, –raw 使用原始格式显示。
-t, –topology 显示拓扑结构信息。

NAME:块设备名。
MAJ:MIN:主要和次要设备号。
RM:设备是否可移动设备。0表示非移动设备,1表示可移动设备
SIZE:设备的容量大小信息。
RO:是否只读,0表示非只读,1表示只读
TYPE:块设备是否是磁盘或磁盘上的一个分区。块设备类型,比如disk磁盘,part分区,lvm逻辑卷,rom只读存储
MOUNTPOINT:设备挂载点

lsblk 命令默认情况下将以树状列出所有块设备。

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
nvme0n1     259:0    0 931.5G  0 disk
├─nvme0n1p1 259:4    0     2M  0 part
├─nvme0n1p2 259:5    0  93.1G  0 part /
└─nvme0n1p3 259:6    0 838.4G  0 part /data
nvme1n1     259:3    0 931.5G  0 disk
nvme2n1     259:2    0 931.5G  0 disk
nvme3n1     259:1    0 931.5G  0 disk

fdisk

fdisk 命令用于观察硬盘实体使用情况,也可对硬盘分区。它采用传统的问答式界面,而非类似DOS fdisk的cfdisk互动式操作界面

参数:
-b<分区大小>:指定每个分区的大小;
-l 列出指定的外围设备的分区表状况;
-s<分区编号>:将指定的分区大小输出到标准输出上,单位为区块;
-u:搭配”-l”参数列表,会用分区数目取代柱面数目,来表示每个分区的起始地址;
-v:显示版本信息。

例如查看磁盘分区情况 fdisk -l /dev/mapper/data_vg-data_lv

sudo fdisk -l /dev/mapper/data_vg-data_lv
磁盘 /dev/mapper/data_vg-data_lv:52.4 GB, 52428800000 字节,102400000 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节

parted

parted 命令用于创建,查看,删除和修改磁盘分区。它是一个磁盘分区和分区大小调整工具。
这个命令算是对fdisk命令的一个补充,一般用于磁盘空间大于2TB大小的磁盘分区,因为如果磁盘大小大于2TB就无法使用fdisk命令进行分区操作了。

如何查看磁盘是否分区?

lsblk 查看磁盘,下面 sda 已分区,sdb 到 sdd 还没分区

# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 139.8G  0 disk
├─sda1   8:1    0     2M  0 part
└─sda2   8:2    0 139.8G  0 part /
sdb      8:16   0   9.1T  0 disk
sdc      8:32   0   9.1T  0 disk
sdd      8:48   0   9.1T  0 disk

查看磁盘分区表

方法1、parted -l 列出系统所有块设备上的所有分区布局
下面 sda 已经做了分区,sdb打了标签但还没分区,sdc还没打标签

# parted -l
Model: ATA INTEL SSDSCKJB15 (scsi)
Disk /dev/sda: 150GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  3146kB  2097kB               primary  bios_grub
 2      3146kB  150GB   150GB   ext4         primary  boot


Model: ATA ST10000NM0016-1T (scsi)
Disk /dev/sdb: 10.0TB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start  End  Size  File system  Name  Flags


Error: /dev/sdc: unrecognised disk label
Model: ATA ST10000NM0016-1T (scsi)
Disk /dev/sdc: 10.0TB
Sector size (logical/physical): 512B/4096B
Partition Table: unknown
Disk Flags:

方法2、parted /dev/sdb 进入指定磁盘的 parted 命令,输入 print 查看是否有分区表,有就是有分区
有分区:

# parted /dev/sdb
GNU Parted 3.1
Using /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: ATA ST10000NM0016-1T (scsi)
Disk /dev/sdb: 10.0TB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  10.0TB  10.0TB  ext4         primary

无分区:

# parted /dev/sdb
GNU Parted 3.1
Using /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: ATA ST10000NM0016-1T (scsi)
Disk /dev/sdb: 10.0TB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start  End  Size  File system  Name  Flags

使用parted命令进行磁盘分区

1、分区
parted /dev/sdb 对磁盘 sdb 进行分区
在 parted 内依次输入命令:
mklabel gpt 修改磁盘分区结构为gpt
mkpart primary 1 -1 划分所有空间到一个主分区
print 打印分区表

# parted /dev/sdb
GNU Parted 3.1
Using /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mklabel gpt
Warning: The existing disk label on /dev/sdb will be destroyed and all data on this disk will be lost. Do you want to continue?
Yes/No? yes
(parted) mkpart primary 1 -1
(parted) print
Model: ATA ST10000NM0016-1T (scsi)
Disk /dev/sdb: 10.0TB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  10.0TB  10.0TB               primary

(parted) quit
Information: You may need to update /etc/fstab.

2、mkfs.ext4 /dev/sdb1 格式化为 ext4 文件系统
等待完成

# mkfs.ext4 /dev/sdb1
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
305201152 inodes, 2441608704 blocks
122080435 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
74512 block groups
32768 blocks per group, 32768 fragments per group
4096 inodes per group
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
    102400000, 214990848, 512000000, 550731776, 644972544, 1934917632

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

3、创建 /data 目录,挂载 sdb 到 /data 目录

# mkdir /data
# mount /dev/sdb1 /data

4、写入 /etc/fstab 使重启生效,否则重启后挂载的磁盘消失
vi /etc/fstab 最后添加
/dev/sdb1 /data ext4 defaults 0 1
保存


smartctl 查看磁盘型号

1、先 fdisk -l 查看硬盘编号
2、使用 smartctl --all /dev/sdb 查看具体磁盘的信息,该命令centos自带

# smartctl --all /dev/sdb
smartctl 6.2 2013-07-26 r3841 [x86_64-linux-3.10.0-514.el7.x86_64] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Device Model:     ST10000NM0016-1TT101
Serial Number:    ZA262MN0
LU WWN Device Id: 5 000c50 0b09db86f
Firmware Version: SBBA
User Capacity:    10,000,831,348,736 bytes [10.0 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Rotation Rate:    7200 rpm
Device is:        Not in smartctl database [for details use: -P showall]
ATA Version is:   ACS-3 (unknown minor revision code: 0x006d)
SATA Version is:  SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is:    Thu Feb 17 16:39:35 2022 CST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

Device Model: ST10000NM0016-1TT101 就是磁盘编号


losetup

Linux losetup (loop setup) 命令用于设置循环设备。
循环设备可把文件虚拟成区块设备,籍以模拟整个文件系统,让用户得以将其视为硬盘驱动器,光驱或软驱等设备,并挂入当作目录来使用。

losetup [ -e encryption ] [ -o offset ] loop_device file
losetup [ -d ] loop_device

-e 表示加密的方式
-o 设置数据偏移量
-d 卸载设备
loop_device 循环设备名,在 linux 下如 /dev/loop0 , /dev/loop1 等。
file 要与循环设备相关联的文件名,这个往往是一个磁盘镜象文件,如 *.img

1、例1
(1)创建空的磁盘镜像文件 floppy.img, 这里创建一个1.44M的软盘
dd if=/dev/zero of=floppy.img bs=512 count=2880

(2)使用 losetup 将磁盘镜像文件虚拟成块设备
losetup /dev/loop1 floppy.img

(3)挂载块设备
mount /dev/loop0 /tmp
经过上面的三步之后,我们就可以通过 /tmp 目录,像访问真实块设备一样来访问磁盘镜像文件 floppy.img

(4)卸载loop设备

$ umount /tmp
$ losetup -d /dev/loop1

2、例2
mount 命令的 -o loop 选项可以将任意一个 loopback 文件系统挂载,相当于先 losetup 再 mount, 例如
mount -o loop loopfile.img /mnt/loopback 等价于下面两条命令:

losetup /dev/loop0 loopfile.img
mount /dev/loop0 /mnt/loopback

实际上,mount -o loop 在内部已经默认的将文件和 /dev/loop0 关联起来了


mount

在 windows 操作系统中,挂载通常是指给磁盘分区(包括被虚拟出来的磁盘分区)分配一个盘符;
在 linux 操作系统中,挂载是指将一个设备(通常是存储设备)挂接到一个已存在的目录上。我们要访问存储设备中的文件,必须将文件所在的分区挂载到一个已存在的目录上,然后通过访问这个目录来访问存储设备。

注意事项:挂载点必须是一个已经存在的目录,这个目录可以不为空,但挂载后这个目录下以前的内容将不可用,umount 以后会恢复正常。

mount [-t vfstype] [-o options] device dir

-t vfstype 指定文件系统的类型,通常不必指定。mount 会自动选择正确的类型。
当前系统支持的文件系统类型是由内核来决定的,可以通过查看 /proc/filesystems 文件来观察当前系统具体都支持哪些文件系统。
proc、tmpfs、sysfs、devpts 等都是 Linux 内核映射到用户空间的虚拟文件系统,它们不和具体的物理设备关联,但它们具有普通文件系统的特征,应用层程序可以像访问普通文件系统一样来访问他们。

常用类型有:
光盘或光盘镜像:iso9660
DOS fat16文件系统:msdos
Windows 9x fat32文件系统:vfat
Windows NT ntfs文件系统:ntfs
Mount Windows文件网络共享:smbfs
UNIX(LINUX) 文件网络共享:nfs

-o, --options <list> 逗号分割的选项列表,主要用来描述设备或档案的挂接方式。常用的参数有:
loop:用来把一个文件当成硬盘分区挂接上系统
ro:采用只读方式挂接设备
rw:采用读写方式挂接设备
iocharset:指定访问文件系统所用字符集

device,要挂接(mount)的设备。

dir,设备在系统上的挂接点(mount point)。

挂载光驱到指定目录
mount /dev/cdrom /mnt/cdrom

修改 /home 目录挂载的磁盘

前提是新机器,没运行任何软件, /home 目录也比较干净
1 lsblk 查看可用的磁盘

# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  3.7T  0 disk
├─sda1   8:1    0    2M  0 part
├─sda2   8:2    0 93.1G  0 part /
└─sda3   8:3    0  3.6T  0 part /data
sdb      8:16   0  3.7T  0 disk
└─sdb1   8:17   0  3.7T  0 part
sdc      8:32   0  3.7T  0 disk
└─sdc1   8:33   0  3.7T  0 part
sdd      8:48   0  3.7T  0 disk
└─sdd1   8:49   0  3.7T  0 part
sde      8:64   0  3.7T  0 disk
└─sde1   8:65   0  3.7T  0 part
sdf      8:80   0  3.7T  0 disk
└─sdf1   8:81   0  3.7T  0 part
sdg      8:96   0  3.7T  0 disk
└─sdg1   8:97   0  3.7T  0 part
sdh      8:112  0  3.7T  0 disk
└─sdh1   8:113  0  3.7T  0 part

2 备份当前 /home 目录
mv home home_bk
前提是新机器,没有部署任何服务,才可以直接将 /home 改名,已经部署服务的线上服务器不能直接将 /home 改名

3 创建新 home
mkdir home

4 磁盘 sdb1 挂载到 /home
mount /dev/sdb1 home

5 home_bk 拷回 home 中
mv home_bk/* home

6 删除 home_bk 目录
rm -r home_bk/

再次 lsblk 可以看到 sdb1 已经挂载到 /home

# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  3.7T  0 disk
├─sda1   8:1    0    2M  0 part
├─sda2   8:2    0 93.1G  0 part /
└─sda3   8:3    0  3.6T  0 part /data
sdb      8:16   0  3.7T  0 disk
└─sdb1   8:17   0  3.7T  0 part /home
sdc      8:32   0  3.7T  0 disk
└─sdc1   8:33   0  3.7T  0 part
sdd      8:48   0  3.7T  0 disk
└─sdd1   8:49   0  3.7T  0 part
sde      8:64   0  3.7T  0 disk
└─sde1   8:65   0  3.7T  0 part
sdf      8:80   0  3.7T  0 disk
└─sdf1   8:81   0  3.7T  0 part
sdg      8:96   0  3.7T  0 disk
└─sdg1   8:97   0  3.7T  0 part
sdh      8:112  0  3.7T  0 disk
└─sdh1   8:113  0  3.7T  0 part

umount

例如 /dev/hda5 已经挂载在 /mnt/hda5 上,用一下三条命令均可卸载挂载的文件系统
umount /dev/hda5
umount /mnt/hda5
umount /dev/hda5 /mnt/hda5


lsscsi

lsscsi 命令的作用是列出 SCSI 设备(或主机)及它们的属性。
SCSI(Small Computer System Interface) 小型计算机系统接口,比如服务器上的磁盘就是SCSI设备。

有的系统上 lsscsi 包默认是不安装的,需要手动安装。
lsscsi 命令能很方便的看出哪些是固态硬盘(SSD),哪些是SATA盘,哪些是FC盘。

-s 显示容量大小
-c 用全称显示默认的信息。
-d 显示设备主,次设备号。

# lsscsi
[0:0:0:0]    disk    ATA      INTEL SSDSC2KB96 0111  /dev/sda
[1:0:0:0]    disk    ATA      ST4000NM0035-1V4 TN02  /dev/sdb

结果解释
第1列:SCSI设备id H:C:T:L ,这里H是指Host,C是指Channel,T是指Id,L是指Lun。
第2列:设备类型。
第3,4,5列:设备厂商,型号,版本信息。
最后一列:设备主节点名。

如何判断是否固态硬盘

1、lsscsi 结果中有 SSD 字样,则是 ssd 硬盘。

2、判断 cat /sys/block/*/queue/rotational 的返回值(其中*为你的硬盘设备名称,例如sda等等)
或者 grep ^ /sys/block/*/queue/rotational 查看全部设备
返回 1 表示磁盘可旋转,所以是HDD
返回 0 表示磁盘不可旋转,所以是SS

grep ^ /sys/block/*/queue/rotational
/sys/block/md0/queue/rotational:1
/sys/block/nvme0n1/queue/rotational:0
/sys/block/sda/queue/rotational:1
/sys/block/sdb/queue/rotational:1
/sys/block/sdc/queue/rotational:1
/sys/block/sdd/queue/rotational:1

3、lsblk -d -o name,rota
使用 lsblk 命令进行判断,参数 -d 表示显示设备名称,参数 -o 表示仅显示特定的列。
ROTA 是 1 的表示可以旋转,是机械硬盘,反之则不能旋转。

$ lsblk -d -o name,rota
NAME    ROTA
sda        1
sdb        1
sdc        1
sdd        1
nvme0n1    0

systemd-detect-virt 判断物理机/虚拟机

物理机上:

# systemd-detect-virt
none

虚拟机上:

$ systemd-detect-virt
xen

用户和工作组管理

su

switch user

su 选项 目标用户

su 命令用于切换当前用户身份到其他用户身份,变更时须输入所要变更的用户帐号与密码。
root 向普通或虚拟用户切换不需要密码
普通用户切换到其它任何用户都需要密码验证

-, -l, --login,切换用户时,使环境变量和欲切换的用户相同
环境变量包括(home目录,shell,user,logname,path等)

例如
su,不加任何参数,默认为切换到 root 用户,但没有转到 root 用户家目录下,也就是说这时虽然是切换为root 用户了,但并没有改变root登录环境
su -,su 加参数 - ,表示默认切换到root用户,并且改变到root用户的环境
su - tom,切换到 tom 用户,并且改变到 tom 用户的环境变量

su 命令和 su - 命令最大的本质区别就是:前者只是切换了root身份,但Shell环境仍然是普通用户的Shell;而后者连用户和Shell环境一起切换成root身份了。su切换成root用户以后,pwd一下,发现工作目录仍然是普通用户的工作目录;而用su -命令切换以后,工作目录变成root的工作目录了。用echo $PATH命令看一下su和su -以后的环境变量,发现会有不同。


sudo

sudo 临时以 root 用户执行命令,经由 sudo 所执行的指令就好像是 root 亲自执行

使用 su 切换到 root 用户执行命令的问题:
仅仅为了一个特权操作就直接赋予普通用户控制系统的完整权限;
当多人使用同一台主机时,如果大家都要使用 su 命令切换到 root 身份,那势必就需要 root 的密码,这就导致很多人都知道 root 的密码;

相对于使用 su 命令还需要新切换用户的密码,sudo 命令的运行只需要知道自己的密码即可,甚至于,我们可以通过手动修改 sudo 的配置文件,使其无需任何密码即可运行。

-b :将后续的命令放到背景中让系统自行运行,不对当前的 shell 环境产生影响。
-u :后面可以接欲切换的用户名,若无此项则代表切换身份为 root 。
-l:此选项的用法为 sudo -l,用于显示当前用户可以用 sudo 执行那些命令。


id

id 命令可以显示真实有效的用户 ID(UID) 和组 ID(GID)。UID 是对一个用户的单一身份标识。组 ID(GID)则对应多个UID。

-g,--group   显示用户所属群组的ID。
-G,–groups 显示用户所属附加群组的ID。
-n,--name   显示用户,所属群组或附加群组的名称。
-r,–real   显示实际ID。
-u,--user   显示用户ID。
-help   显示帮助。
-version   显示版本信息。

$ id
uid=1000(centos) gid=1000(centos) 组=1000(centos),4(adm),10(wheel),190(systemd-journal),994(docker)
$ id -u
1000
$ id -g
1000

如何读取输出:
用户jboss5的uid号码为4034,gid号码是214,用户jboss是下面组的成员:组groups(gid为214)


useradd

只有 root 账号才可以使用此命令。
useradd 命令用于 Linux 中创建的新的系统用户。useradd 可用来建立用户帐号。帐号建好之后,再用 passwd 设定帐号的密码.而可用 userdel 删除帐号。使用 useradd 指令所建立的帐号,实际上是保存在 /etc/passwd 文本文件中。
在 Red Hat Linux 中,adduser 命令则是 useradd 命令的符号连接,两者实际上是同一个指令。

示例
useradd testuser,创建用户testuser
passwd testuser 给已创建的用户testuser设置密码
说明:新创建的用户会在/home下创建一个用户目录testuser

在root权限下,useradd只是创建了一个用户名,如 (useradd +用户名 ),它并没有在/home目录下创建同名文件夹,也没有创建密码,因此利用这个用户登录系统,是登录不了的,为了避免这样的情况出现,可以用 (useradd -m +用户名)的方式创建,它会在/home目录下创建同名文件夹,然后利用( passwd + 用户名)为指定的用户名设置密码。

选项
-c<备注>:加上备注文字。备注文字会保存在passwd的备注栏位中;
-d<登入目录>:指定用户登入时的启始目录;
-D:变更预设值;
-e<有效期限>:指定帐号的有效期限;
-f<缓冲天数>:指定在密码过期后多少天即关闭该帐号;
-g<群组>:指定用户所属的群组;
-G<群组>:指定用户所属的附加群组;
-m, --create-home 自动建立用户的登入目录;
-M:不要自动建立用户的登入目录;
-n:取消建立以用户名称为名的群组;
-r:建立系统帐号;
-s:指定用户登入后所使用的shell;
-u:指定用户id。


userdel

userdel 命令用于删除给定的用户,以及与用户相关的文件。若不加选项,则仅删除用户帐号,而不删除相关文件。

-f:强制删除用户,即使用户当前已登录;
-r:删除用户的同时,删除与用户相关的所有文件。
请不要轻易用-r选项;他会删除用户的同时删除用户所有的文件和目录,切记如果用户目录下有重要的文件,在删除前请备份。

userdel testuser 删除用户testuser


passwd 修改口令

passwd 作为普通用户和超级权限用户都可以运行,但作为普通用户只能更改自己的用户密码,但前提是没有被 root 用户锁定;如果 root 用户运行 passwd 可以设置或修改任何用户的密码。
passwd 命令后面不接任何参数或用户名,则表示修改当前用户的密码;

用户账号刚创建时没有口令,但是被系统锁定,无法使用,必须为其指定口令后才可以使用,即使是指定空口令。

passwd username:修改用户username的密码,仅root用户可修改其他用户的密码。

-l 锁定口令,即禁用账号。
-u 口令解锁。
-d 使账号无口令。
-f 强迫用户下次登录时修改口令。


gpasswd

gpasswd 命令是 Linux 下工作组文件 /etc/group/etc/gshadow 管理工具。

-a 添加用户到组;
-d:从组删除用户;
-A:指定管理员;
-M:指定组成员和-A的用途差不多;
-r:删除密码;
-R:限制用户登入组,只有组中的成员才可以用newgrp加入该组。

gpasswd -a user_name group_name 添加用户 user_name 到组 group_name, 同时保留用户之前的用户组

修改用户的工作组

1、修改用户的用户组可以使用 usermod -G group_name user_name, 注意这个命令可以添加一个用户到指定的组,但是以前添加的组就会清空掉。

2、添加用户到某一个组,同时保留用户之前的用户组,可以加上 -a 参数 usermod -G group_name user_name

3、添加用户到某一个组,同时保留用户之前的用户组,还可以使用 gpasswd 这个命令来添加操作用户:gpasswd -a user_name group_name


usermod

修改用户账号就是根据实际情况更改用户的有关属性,如用户号、主目录、用户组、登录Shell等。
usermod 选项 用户名
常用的选项包括-c, -d, -m, -g, -G, -s, -u以及-o等,这些选项的意义与useradd命令中的选项一样,可以为用户指定新的资源值。

-c<备注>:修改用户帐号的备注文字;
-d<登入目录>:修改用户登入时的目录;
-e<有效期限>:修改帐号的有效期限;
-f<缓冲天数>:修改在密码过期后多少天即关闭该帐号;
-g<群组>:修改用户所属的群组;
-G, --groups GROUPS 修改用户所属的附加群组
-a, --append GROUP 将用户追加至上边 -G 中提到的附加组中,并不从其它组中删除此用户
-l<帐号名称>:修改用户帐号名称;
-L 锁定用户密码,使密码无效;
-U 解除密码锁定。
-s <shell> 修改用户登入后所使用的shell;
-u <uid> 修改用户ID;

例如
usermod -s /bin/ksh -d /home/z –g developer sam
此命令将用户sam的登录Shell修改为ksh,主目录改为/home/z,用户组改为developer。

usermod -aG wheel testuser 将用户加入 wheel 用户组
sudo usermod -aG docker $USER 将当前用户加入 docker 组

This account is currently not available

修改完 elasticsearch 用户的密码,su 切换时提示 This account is currently not available

原因: elasticsearch 账号被禁止登录了
cat /etc/passwd | grep elasticsearch 查看 elasticsearch 账号信息
elasticsearch:x:991:986:elasticsearch user:/nonexistent:/sbin/nologin
发现它的 shell 是 /sbin/nologin

解决:将 elasticsearch 账号的 shell 改成 /bin/bash
sudo usermod -s /bin/bash elasticsearch
或者直接编辑 /etc/passwd


last

last 命令用于显示用户最近登录信息。
单独执行 last 命令,它会读取 /var/log/wtmp 文件,并把该给文件的内容记录的登入系统的用户名单全部显示出来。

last 命令的数据源是 /var/log/wtmp(默认 记录每个用户的登录次数和持续时间等信息)和 /var/log/btmp (详细,包括登录失败请求)

第一列:用户名
第二列:终端位置。pts/0 (伪终端) 意味着从诸如 SSH 或 telnet 的远程连接的用户。tty (teletypewriter) 意味着直接连接到计算机或者本地连接的用户。
第三列:登录ip或者内核 。如果你看见:0.0 或者什么都没有,这意味着用户通过本地终端连接。除了重启活动,内核版本会显示在状态中。
第四列:开始时间
第五列:结束时间(still login in 还未退出 down 直到正常关机 crash 直到强制关机)
第六列:持续时间 188+11:35 表示 188天11小时35分

用户名 终端位置 登录IP或内核 开始时间 - 结束时间 持续时间

# last
centos   pts/0        111.198.225.229  Sun Apr 19 18:09   still logged in
centos   pts/0        111.198.225.229  Sat Apr 18 21:49 - 01:06  (03:17)
centos   pts/0        220.194.45.154   Thu Apr  2 19:05 - 21:36  (02:30)
centos   pts/0        220.194.45.154   Thu Apr  2 12:54 - 16:16  (03:22)
centos   pts/0        220.194.45.154   Wed Apr  1 11:49 - 11:58  (00:08)
centos   pts/0        220.194.45.154   Tue Mar 24 13:01 - 13:54  (00:53)
centos   pts/0        220.194.45.154   Tue Mar 17 17:05 - 21:50  (04:44)
centos   pts/0        220.194.45.154   Tue Mar 17 10:51 - 15:07  (04:16)
centos   pts/0        111.198.226.65   Mon Mar 16 12:07 - 12:52  (00:45)
centos   pts/0        111.198.226.65   Sat Mar 14 22:03 - 00:19  (02:16)

last reboot 查看系统重启次数和时间

last reboot 查看系统上次重启时间

# last reboot
reboot   system boot  4.19.157         Wed Aug 31 09:19 - 20:54 (188+11:35)
reboot   system boot  4.19.157         Thu Aug  4 17:53 - 09:16 (26+15:23)
reboot   system boot  4.19.157         Thu Jul 28 11:04 - 09:16 (33+22:12)
reboot   system boot  3.10.0-957.el7.x Wed Jul 27 18:50 - 09:16 (34+14:26)

chroot

chroot,即 change root directory (更改 root 目录)。
在 linux 系统中,系统默认的目录结构都是以 / 即以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 root
一个正在运行的进程经过 chroot 操作后,其根目录将被显式映射为某个指定目录,它将不能够对该指定目录之外的文件进行访问动作。这是一种非常简单的资源隔离化操作,类似于现在 Linux 的 Mount Namespace 功能。

在现今的 Linux 上,chroot 既是一个命令行工具(chroot(8)),又是一个系统调用(chroot(2))

chroot [OPTION] NEWROOT [COMMAND [ARGS]...]
COMMAND 指的是切换 root 目录后需要执行的命令,如果没有指定,默认是 ${SHELL} -i,大部分情况是 /bin/bash。执行 chroot(8) 需要使用 root 权限。

chroot 命令小记
https://juejin.im/post/6844903592466317319


chsh

chsh 命令用来更换登录系统时使用的 shell
若不指定任何参数与用户名称,则 chsh 会以应答的方式进行设置。

查看系统安装了哪些shell:
cat /etc/shells

# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

查看当前正在使用的shell:
1、查看 $SHELL 变量的值

echo $SHELL
/bin/bash

注意SHELL一定要是大写。

2、查看 $0 变量的值:

echo $0
-zsh

把我的shell改成zsh:
chsh -s /bin/zsh
使用chsh加选项-s就可以修改登录的shell了!你会发现你现在执行echo $SHELL后仍然输出为/bin/bash,这是因为你需要重启你的shell才完全投入到zsh怀抱中去。chsh -s其实修改的就是/etc/passwd文件里和你的用户名相对应的那一行。


w

w 命令用于显示已经登陆系统的用户列表,并显示用户正在执行的指令。
执行这个命令可得知目前登入系统的用户有那些人,以及他们正在执行的程序。
单独执行 w 命令会显示所有的用户,您也可指定用户名称,仅显示某位用户的相关信息。

该命令所使用的信息来源于 /var/run/utmp 文件。

w 命令输出的信息包括:
用户名称
用户的机器名称或tty号
远程主机地址
用户登录系统的时间
空闲时间(作用不大)
附加到tty(终端)的进程所用的时间(JCPU时间)
当前进程所用时间(PCPU时间)
用户当前正在使用的命令

$ w
 15:42:33 up 41 days, 16:44,  2 users,  load average: 0.04, 0.09, 0.13
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
centos   pts/0    61.111.129.80    15:18    9.00s  0.00s  0.00s -bash
centos   pts/2    61.111.129.80    15:42    1.00s  0.00s  0.00s w

who

who 命令是显示目前登录系统的用户信息。
执行 who 命令可得知目前有那些用户登入系统,单独执行 who 命令会列出登入帐号,使用的终端机,登入时间以及从何处登入或正在使用哪个X显示器。
其输出为:用户名、tty号、时间日期、主机地址。

$ who
centos   pts/2        2020-08-08 15:42 (61.111.129.80)

users

users 命令用于显示当前登录系统的所有用户的用户列表。
每个显示的用户名对应一个登录会话。如果一个用户有不止一个登录会话,那他的用户名将显示相同的次数。

$ users
centos

whoami

whoami 命令用于打印当前有效的用户名称,相当于执行 id -un 命令。

[centos@centos ~]$ whoami
centos
[centos@centos ~]$ id -un
centos

who am i

linux 中 who am iwhoami 命令是不一样的,简单来说:
who am i 是记录登录 shell 时的用户,你以什么用户登录就显示什么
whoami 这个才是当前系统的有效用户
举个例子:
我以 root 用户登录系统,然后执行 su - centos 切换到 centos 用户下,此时 who am i 显示的是 root 用户,而 whoami 则显示 centos 用户。


last

last 命令可用于显示特定用户登录系统的历史记录。
如果没有指定任何参数,则显示所有用户的历史信息。
在默认情况下,这些信息(所显示的信息)将来源于 /var/log/wtmp 文件。
该命令的输出结果包含以下几列信息:
用户名称
tty设备号
历史登录时间日期
登出时间日期
总工作时间

[centos@centos ~]$ last
centos   pts/2        61.135.139.80    Sat Aug  8 15:42   still logged in
centos   pts/1        61.135.139.80    Sat Aug  8 15:38 - 15:42  (00:03)
centos   pts/0        61.135.139.80    Sat Aug  8 15:18 - 15:44  (00:25)
centos   pts/0        61.135.139.80    Mon Aug  3 13:52 - 13:56  (00:04)
centos   pts/0        61.135.139.80    Mon Aug  3 13:51 - 13:52  (00:00)
centos   pts/0        61.135.139.80    Wed Jul 29 09:59 - 13:03  (03:04)
centos   pts/0        111.198.229.62   Sun Jul 19 00:25 - 00:33  (00:08)
centos   pts/0        61.122.167.80    Mon Jul 13 17:21 - 19:36  (02:14)

进程和作业管理

ps

ps 命令用于报告当前系统的进程状态快照。
-e 显示所有进程, 等于 -A
-f 全格式输出
-p pidlist 查看指定 pid 的进程
-o format 输出自定义列 format 是空格分隔或者逗号分割的列名
-l 显示 PRI NI 等优先级信息

ps -ef 查看所有进程( **标准Unix语法,带-**)
ps -ef|cat 命令太长时展示不全,接 cat 命令可换行输出
输出列:
UID PID PPID C STIME TTY TIME CMD
UID:用户ID
PID:进程ID
PPID:父进程ID
C:CPU占用率
STIME:开始时间
TTY:开始此进程的TTY
TIME:此进程运行的总时间
CMD:命令

# ps -ef|head
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Jan22 ?        00:07:44 /usr/lib/systemd/systemd --system --deserialize 20
root         2     0  0 Jan22 ?        00:00:01 [kthreadd]
root         3     2  0 Jan22 ?        00:00:00 [rcu_gp]
root         5     2  0 Jan22 ?        00:00:00 [kworker/0:0H]
root         7     2  0 Jan22 ?        00:00:00 [mm_percpu_wq]
root         8     2  0 Jan22 ?        00:20:57 [ksoftirqd/0]
33         485   359  0 Jan28 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf

ps aux 查看所有进程( BSD风格语法,不带-
ps -ejH 查看所有进程的层次关系,即进程树
ps axjf 查看所有进程的层次关系
ps -p pid -o vsz,rss 查看指定 pid 的虚拟内存 vsz 大小(单位kb)和常驻内存 rss 大小(单位kb)

ps -p pid -o lstart 查看指定 pid 的启动时间

# ps -p 31067 -o lstart
                 STARTED
Fri Oct 29 11:13:26 2021

ps -efl 显示优先级信息

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
4 S root         1     0  0  80   0 - 49614 -      Jul07 ?        00:01:28 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
1 S mysql    78137     1 99  80   0 - 12726943 -   Jul16 ?        10-12:19:04 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

PRI: 即进程的优先级,pri 值越小优先级越高
NI: nice 值,表示进程可被执行的优先级的修正数值。进程真正的优先级等于 pri + nice 所以当 nice 为负值的时候,该程序的pri变小,优先级越高。
这也说明,nice 值越小,这个进程越不 nice, 抢占 cpu 的能力就越强,最终的优先级就越高。nice 值也做静态优先级。
所以,尽管进程的 nice 值不是进程的优先级,但是会影响进程优先级的变化。


pstree

pstree 查看进程树
pstree -p 查看进程树,并打印每个进程的PID
pstree -p pid 查看某个进程树型结构

# pstree
systemd─┬─abrt-watch-log
        ├─abrtd
        ├─agetty
        ├─ansible-agent───25*[{ansible-agent}]
        ├─atd
        ├─77*[containerd-shim─┬─pause]
        ├─containerd-shim─┬─pgpool───36*[pgpool]
        │                 └─12*[{containerd-shim}]
        ├─containerd-shim─┬─bash
        │                 └─11*[{containerd-shim}]
        ├─crond
        ├─dbus-daemon
        ├─dockerd─┬─containerd───89*[{containerd}]
        │         ├─2*[docker-proxy───7*[{docker-proxy}]]
        │         ├─2*[docker-proxy───6*[{docker-proxy}]]
        │         └─199*[{dockerd}]
        ├─etcd───102*[{etcd}]
        ├─irqbalance
        ├─java───186*[{java}]
        ├─kubelet───109*[{kubelet}]
        ├─lsmd
        ├─lvmetad
        ├─master─┬─2*[bounce]
        │        ├─3*[cleanup]
        │        ├─2*[local]
        │        ├─pickup
        │        ├─qmgr
        │        └─trivial-rewrite
        ├─polkitd───5*[{polkitd}]
        ├─registry───65*[{registry}]
        ├─rngd
        ├─rpcbind
        ├─rsyslogd───2*[{rsyslogd}]
        ├─smartd
        ├─socat
        ├─sshd─┬─sshd───bash───bash───pstree
        │      └─2*[sshd───bash───bash]
        ├─systemd-journal
        ├─systemd-logind
        └─systemd-udevd

pgrep

pgrep [options] <pattern> 显示和 pattern 相关的当前进程,只返回进程号

-f 默认 pgrep 只匹配进程名,不匹配启动参数中的字符串。加 -f 参数后会匹配全部启动参数。

pgrep 相当于 ps -e -o pid,cmd | awk '{print $1,$2}' | grep pattern

例如,查看nginx的进程号
pgrep nginx


nohup

在命令前加nohup,关闭终端后依然执行,常用于跑一些运行时间很长的程序

nohup Command [ Arg … ][ & ]

nohup 命令运行由 Command 参数和任何相关的 Arg 参数指定的命令,忽略所有挂断(SIGHUP)信号,如果当前bash关闭,则当前进程会挂载到init进程下,成为其子进程,这样即使退出当前用户程序也可继续执行。 在注销后使用 nohup 命令运行后台中的程序。要运行后台中的 nohup 命令,添加 &到命令的尾部。

nohup&

当在前台运行某个作业时,终端被该作业占据;可以在命令后面加上& 实现后台运行。例如:sh test.sh &
不过,作业在后台运行一样会将结果输出到屏幕上,干扰你的工作。如果放在后台运行的作业会产生大量的输出,最好使用下面的方法把它的输出重定向到某个文件中:
command > out.file 2>&1 &
这样,所有的标准输出和错误输出都将被重定向到一个叫做 out.file 的文件中。
2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了out.file文件,即将标准出错也输出到out.file文件中。试想2>1代表什么,2与>结合代表错误重定向,而1则代表错误重定向到一个文件1,而不代表标准输出;换成2>&1&与1结合就代表标准输出了,就变成错误重定向到标准输出

使用&命令后,作业被提交到后台运行,当前控制台没有被占用,但是一但把当前控制台关掉(退出帐户时),作业就会停止运行。nohup命令可以在你退出帐户之后继续运行相应的进程。
nohup就是不挂起的意思(no hang up)该命令的一般形式为:
nohup command &

nohup后命令依然停止

使用了 nohup 之后,很多人就这样不管了,其实这样有可能在当前账户非正常退出或者结束的时候,命令还是自己结束了。
所以在使用 nohup 命令后台运行命令之后,需要使用 exit 正常退出当前账户,这样才能保证命令一直在后台运行。

linux后台执行命令:&和nohup
https://www.cnblogs.com/zzyoucan/p/7764590.html

ctrl+z放到后台并挂起

ctrl-c: ( kill foreground process ) 发送 SIGINT 信号给前台进程组中的所有进程,强制终止程序的执行;

ctrl-z: ( suspend foreground process ) 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程,而并非结束进程。
ctrl-z 将任务中断,但是此任务并没有结束,他仍然在进程中,只是放到后台并维持挂起的状态。如需其在后台继续运行,需用“bg job号”使其继续运行;再用”fg job号”可将后台进程前台化。

用户可以使用使用 fg/bg 操作恢复执行前台或后台的进程。fg命令在前台恢复执行被挂起的进程,此时可以使用ctrl-z再次挂起该进程,bg命令在后台恢复执行被挂起的进程,而此时将无法使用 ctrl-z 再次挂起该进程;

一个比较常用的场景:
正在使用vi编辑一个文件时,需要执行shell命令查询一些需要的信息,可以使用ctrl-z挂起vi,等执行完shell命令后再使用fg恢复vi继续编辑你的文件

& 将指令丢到后台中去执行
ctrl+z 将前台任务丢到后台中暂停
jobs 查看后台的工作状态
fg jobnumber 将后台的任务拿到前台来处理
bg jobnumber 将任务放到后台中去处理

There are stopped jobs.

在Linux的shell中输入exit或者logout命令时有时会出现 there are stopped jobs

原因:
这是由于按下了 Ctrl+Z 之后使程序或者进程被挂起。

解决:
在 shell 中输入命令 jobs 可以查看后台运行的进程列表
输入命令 jobs -l 可看到 pid,然后选择杀死 kill pid 或者 fg 任务号 转为前台。


jobs

jobs 命令用于显示 Linux 中的任务列表及任务状态,包括后台运行的任务。该命令可以显示任务号及其对应的进程号。其中,任务号是以普通用户的角度进行的,而进程号则是从系统管理员的角度来看的。一个任务可以对应于一个或者多个进程号。

# jobs -l
[1]+ 86585 Stopped                 python myhttp.py 8123

输出信息的第一列表示任务编号,第二列表示任务所对应的进程号,第三列表示任务的运行状态,第四列表示启动任务的命令。

exit 时提示 There are stopped jobs

exit 或 logout 时提示 There are stopped jobs,是因为之前 ctrl+z 将某个命令或进程放入后台了
jobs -l 可以看到后台任务
可直接 kill pid 杀掉后台进程,例如 kill 86585
或者 kill 百分号%+job序号 杀掉后台进程,例如 kill %1
或者 fg 1 转为前台再 ctrl+c 退出

fg

fg 命令用于将后台作业(在后台运行的或者在后台挂起的作业)放到前台终端运行。与 bg 命令一样,若后台任务中只有一个,则使用该命令时,可以省略任务号。

fg 1 将1号任务从后台执行转换到前台执行

bg

bg 命令用于将作业放到后台运行,使前台可以执行其他任务。该命令的运行效果与在指令后面添加符号 & 的效果是相同的,都是将其放到系统后台执行。

如果系统中只有一个挂起的任务时,即使不为该命令设置参数”1”,也可以实现这个功能。


目录基本操作

cd

cd /,返回根目录,即/
cd -,返回进入此目录之前所在的目录,即环境变量OLDPWD所表示的目录
cd,cd后什么都不加,等于cd ~,进入当前用户家目录
cd ~,回到当前用户家目录
如果是以root身份登录,执行此命令后,回到/root/目录下
如果是以其他用户(例如masi)等录的话,则是回到/home/masi目录下。

.,当前目录
..,上一级目录
cd ..,返回上一级
cd ../..,返回上两级目录

No space left on device

磁盘空间满的时候,tab 自动补全也无法使用,提示:
bash: cannot create temp file for here-document: No space left on device

根目录和家目录

根目录即 /
家目录,除 root 用户之外的用户的家目录是 /home/用户名
root 用户的家目录为 /root


pwd

输出当前目录,pwd命令以绝对路径的方式显示用户当前工作目录。命令将当前目录的全路径名称(从根目录)写入标准输出。


dirname

dirname 命令去除文件名中的非目录部分,仅显示与目录有关的内容。
dirname 命令读取指定路径名保留最后一个 / 及其前面的字符,删除其他部分,并写结果到标准输出。如果最后一个 / 后无字符,dirname 命令使用倒数第二个/,并忽略其后的所有字符。

dirname //
/
dirname /a/b/
/a
dirname a
.
dirname a/b
a

basename

打印目录或者文件的基本名称

basename //
/
basename /a/b/
b
basename a
a
basename a/b
b

cp

cp [options] source1 source2 source3 .... directory
cp 可以将单个源文件复制成一个指定文件名的具体文件,用于拷贝并改名。
默认情况下,cp命令不能复制目录,如果要复制目录,则必须使用-R选项;
当“源文件”为多个文件时,要求“目标文件”为指定的目录。

选项
-r/R,递归处理,将指定目录下的所有文件与子目录一并处理,用于目录的复制行为。此时目标文件必须为一个目录名。
-f,删除已经存在的目标文件而不提示。
-i,和f选项相反,在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,是交互式拷贝。
-v,详细显示命令执行的操作。

复制指定目录下的全部文件到另一个目录中
假设复制源目录为/home/masi/dir1,目标目录为/home/masi/dir2
如果dir2目录不存在,则使用命令:cp -r /home/masi/dir1 /home/masi/dir2,将拷贝dir1并改名为目录dir2
如果dir2目录已存在,则使用目录:cp -r /home/masi/dir1 /home/masi/dir2,拷贝后dir1成为dir2的子目录


mv

mv 命令用来对文件或目录重新命名,或者将文件从一个目录移到另一个目录中。

mv [选项] 源文件或目录 目标文件或目录
如果“目标文件”是文件名则在移动文件的同时,将其改名为“目标文件”;如果“目标文件”是目录名则将源文件移动到“目标文件”下。

-f,若目标文件或目录与现有的文件或目录重复,则直接覆盖现有的文件或目录;

改文件名
例如,将当前目录中的readme.txt改名为readme.doc
mv readme.txt readme.doc


rename

Mac rename 命令:
brew install rename 安装 rename 命令

rename 's/人脸/00-人脸/' 人脸*.jpg 将 人脸开头的jpg 图片中的 人脸 批量改名 替换为 00-人脸,类似 sed s 命令的格式。


rm

对于链接文件,只是删除整个链接文件,而原有文件保持不变。

-f,强制删除,不提示
-r/R,递归删除,用于删除文件夹

rm: Argument list too long

log 目录下有 300 多个文件
rm -f log/core.2021-4* 报错 -bash: /usr/bin/rm: Argument list too long
解决:
改为 find log/ -name "core.2021-4*" -delete

Argument list too long error for rm, cp, mv commands
https://stackoverflow.com/questions/11289551/argument-list-too-long-error-for-rm-cp-mv-commands


mkdir

-p/--parents,若所要建立目录的上层目录目前尚未建立,则会一并建立上层目录,用于递归建立文件夹
-m <目标属性>/--mode <目标属性>,建立目录的同时设置目录的权限;

在当前目录中建立bin和bin下的os_1目录,权限设置为文件主可读、写、执行,同组用户可读和执行,其他用户无权访问
mkdir -p-m 750 bin/os_1

同时创建/home/test1/test2、/home/test3/test4 目录
mkdir -p /home/{test1/test2,test3/test4}


ls

选项
-a,显示所有文件和目录(以.开头的文件是隐藏文件,默认不显示)
-t,用文件和目录的更改时间排序(默认为文件名排序),最近修改的文件显示在最前面。
-d,仅显示目录名,而不显示目录下的内容列表。显示符号链接文件本身,而不显示其所指向的目录列表;
-l,以长格式显示目录下的内容列表,包含档案的属性与权限等等数据。
-i, --inode 输出 inode 号
例如:
-rwxr-xr-x. 1 root root 23832 May 11 2016 env
从左到右依次为文件属性、连接数、文件拥有者、文件所属用户组、文件大小、最后修改时间、文件名

ll 结果详解

  • 第一个栏位,表示文件的属性。
    第一个字符,表示这个文件的类型,常见的有:文件-, 目录d, 连接文件l, 块设备b, 字符设备c
    后九个属性中,每三个位一组,”r”表示可读(read)、”w”表示可写(write)、”x”表示可执行(excute),分别对应owner、group、others的权限。
  • 第二个栏位,表示文件个数。如果是文件的话,那这个数目自然是1了,如果是目录的话,那它的数目就是该目录中的文件个数了。
  • 第三个栏位,表示该文件或目录的拥有者。若使用者目前处于自己的Home, 那这一栏大概都是它的账号名称。
  • 第四个栏位,表示所属的组(group)。每一个使用者都可以拥有一个以上的组,不过大部分的使用者应该都只属于一个组,只有当系统管理员希望给予某使用者特殊权限时,才可能会给他另一个组。
  • 第五栏位,表示文件大小。文件大小用byte来表示,而空目录一般都是1024byte,当然可以用其它参数使文件显示的单位不同,ls –k 则以kb为单位。  
  • 第六个栏位,表示最后一次修改时间。以“月,日,时间”的格式表示,如Aug 15 5:46表示8月15日早上5:46分。
  • 第七个栏位,表示文件名。我们可以用 ls –a 显示隐藏的文件名。

ll 预定义的命令别名,用于列出所有内容及详细信息,which ll 结果为 alias ll='ls -l --color=auto'
ll -h,以更易读的方式显示文件大小

目录下文件过多导致ls卡住

一个目录下有 300 多个日志文件,ls 直接卡死

默认情况下,ls命令会将输出排序。为了排序,ls命令先将所有文件的名称读入内存。当遇到一个非常大的目录时,它就在那里不断地读入文件名,并且内存占用越来越大,直到将所有文件一次性以字母数字顺序列出来。

改用 ls -1 -f 可以立即显示出文件, ls -1 -f 命令并不执行排序操作,只是读取目录然后立即显示文件。


文件权限属性设置

stat

通过stat命令查看文件的状态

linux系统的文件时间

linux系统“文件时间”主要包括三个内容:

  • 修改时间(modification time, 简称mtime):当前文件“内容数据”更改时,这个属性被更新,使用ls命令显示的时间就是修改时间mtime
  • 状态时间(status time, 简称ctime):是该文件的i节点最后一次被修改的时间,通过chmod、chown命令修改一次文件属性,这个时间就会更新。
  • 访问时间(access time, 简称atime):当读取文件内容时,这个属性被更新,比如对这个文件运用 more、cat等命令。注意ls、stat命令都不会修改文件的访问时间。

Linux中如何查看文件的最初创建时间?
在Linux中,没有文件创建时间的概念。只有文件的访问时间、修改时间、状态改变时间。也就是说不能知道文件的创建时间。但如果文件创建后就没有修改过,修改时间=创建时间;如果文件创建后,状态就没有改变过,那么状态改变时间=创建时间;如果文件创建后,没有被读取过,那么访问时间=创建时间,这个基本不太可能。


chmod

chmod [options] mode files
-R/--recursive,对目前目录下的所有档案与子目录进行相同的权限变更(即以递归的方式逐个变更)

linux文件属性

第一个字符,表示这个文件的类型,常见的有:文件-, 目录d, 连接文件l, 块设备b, 字符设备c
后九个属性中,每三个位一组,”r”表示可读(read)、”w”表示可写(write)、”x”表示可执行(excute),分别对应owner、group、others的权限。
第一组为“拥有者owner的权限”;
第二组为“同用户组的权限”;
第三组为“其他人的权限”;

权限设定字符串
权限设定字符串mode格式如下 : [ugoa…][[+-=][rwxX]…][,…]
其中 u 表示该档案的拥有者,g 表示与该档案的拥有者属于同一个群体(group)者,o 表示其他以外的人,a 表示这三者皆是。
+表示增加权限、-表示取消权限、=表示唯一设定权限。
r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有目标文件对某些用户是可执行的或该目标文件是目录时才追加x 属性。

数字表示
此外我们多数用三位八进制数字的形式来表示权限,第一位指定属主的权限,第二位指定组权限,第三位指定其他用户的权限,每位通过4(读100)、2(写010)、1(执行001)三种数值的和来确定权限。如6(4+2)代表有读写权,7(4+2+1)有读、写和执行的权限。
例如:
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=5。
还可设置第四位,它位于三位权限序列的前面,第四位数字取值是4,2,1,代表意思如下:
4,执行时设置用户ID,用于授权给基于文件属主的进程,而不是给创建此进程的用户。
2,执行时设置用户组ID,用于授权给基于文件所在组的进程,而不是基于创建此进程的用户。
1,设置粘着位。

chmod a=rwx file 和 chmod 777 file 效果相同
chmod ug=rwx,o=x file 和 chmod 771 file 效果相同
若用chmod 4755 filename可使此程序具有root的权限

1、将档案 file1.txt 设为所有人皆可读取 :
chmod ugo+r file1.txt

2、将档案 file1.txt 设为所有人皆可读取 :
chmod a+r file1.txt

3、将档案 file1.txt 与 file2.txt 设为该档案拥有者,与其所属同一个群体者可写入,但其他以外的人则不可写入 :
chmod ug+w,o-w file1.txt file2.txt

4、将 ex1.py 设定为只有该档案拥有者可以执行 :
chmod u+x ex1.py

5、将目前目录下的所有档案与子目录皆设为任何人可读取 :
chmod -R a+r *


chown

chown命令改变某个文件或目录的所有者和所属的组,该命令可以向某个用户授权,使该用户变成指定文件的所有者或者改变文件所属的组。用户可以是用户或者是用户 ID,用户组可以是组名或组 ID。文件名可以使由空格分开的文件列表,在文件名中可以包含通配符。

只有文件主和超级用户才可以便用该命令。
chown [-cfhvR] [--help] [--version] user[:group] file...

user : 新的文件拥有者的使用者 ID
group : 新的文件拥有者的使用者组(group)
-c : 显示更改的部分的信息
-f : 忽略错误信息
-h :修复符号链接
-v : 显示详细的处理信息
-R,--recursive : 处理指定目录以及其子目录下的所有文件
–help : 显示辅助说明
–version : 显示版本

将目录 /usr/meng 及其下面的所有文件、子目录的文件主改成 liu
chown -R liu /usr/meng

把 file 文件的文件主改为 user
chown user file

把 file 文件的文件主改为 user,所属group改为 group
chown user:group file

chgrp

chgrp命令用来改变文件或目录所属的用户组。该命令用来改变指定文件所属的用户组。其中,组名可以是用户组的id,也可以是用户组的组名。文件名可以 是由空格分开的要改变属组的文件列表,也可以是由通配符描述的文件集合。如果用户不是该文件的文件主或超级用户(root),则不能改变该文件的组。

在UNIX系统家族里,文件或目录权限的掌控以拥有者及所属群组来管理。您可以使用chgrp指令去变更文件与目录的所属群组,设置方式采用群组名称或群组识别码皆可。

将/usr/meng及其子目录下的所有文件的用户组改为mengxin
chgrp -R mengxin /usr/meng

file

file命令用于辨识文件类型

1、查看文件的编码格式
file xx.log
xx.log: UTF-8 Unicode text, with very long lines


文件查找和比较

find

find <指定目录> <指定选项> <指定动作>
如果什么参数也不加,find 默认搜索当前目录及其子目录,并且不过滤任何结果(也就是返回所有文件),将它们全都显示在屏幕上。
可同时搜索多个指定目录,注意目录之间要用空格分开

查找目录:find /(查找范围) -name '查找关键字' -type d
查找文件:find /(查找范围) -name 查找关键字 -print

选项:
-name pattern, 指定文件名 pattern, 可使用正则表达式, 只匹配文件名不匹配路径
-iname pattern,此参数的效果和指定 -name 参数类似,但忽略字符大小写的差别
-type b/d/c/p/l/f,指定文件类型,b块设备、d目录、c字符设备、p管道、l符号链接、f普通文件
-empty 查找系统中空白的文件或目录,或目录中没有子目录的文件夹
-maxdepth n 设置最大目录层级
-links 连接数目 查找符合指定的硬连接数目的文件或目录,find / -type f -links 2 查找硬链接数为的文件

指定动作:
-exec find 命令对匹配的文件执行该参数所给出的Shell命令。
-ok 和 -exec的作用相同,只是更安全,在执行每个命令之前,都会给出提示,让用户来确定是否执行。
{} 代表前面查找出来的文件
-delete 删除查到的文件或目录

使用示例:

查找并删除当前目录及其子目录下的所有.DS_Store 文件:
find . -name '*.DS_Store' -type f -delete
find . -name '.DS_Store' | xargs rm -f

查找/etc /tmp /root目录下名为passwd的文件,注意目录之间要用空格分开
find /etc /tmp /root -name passwd

搜索当前目录(含子目录,以下同)中,所有文件名以my开头的文件
find . -name my*

查/home目录下以两个小写字母和两个数字开头的txt文件
find /home -name [a-z][a-z][0–9][0–9].txt -print

查找tomcat7文件夹所在的位置
find / -name 'tomcat7' -type d

查找server.xml文件的位置
find / -name 'server.xml' -print

查找所有名字包含nginx的文件,并管道连接ll -ah命令列出详细信息
sudo find / -name 'nginx' |ll -ah

忽略查询报错

find 搜索时可能会有大量 Permission denied 等错误把搜索结果都淹没了
find: ‘/proc/15713’: No such file or directory
find: /usr/sbin/server: Permission denied

可以增加 2>/dev/null 将错误信息重定向到 /dev/null,例如 find / -name "*fastjson*" 2>/dev/null

查找空目录并删除

查出当前目录(包含子目录)下所有空文件夹
find . -type d -empty

查出当前目录(不包含子目录)下所有空文件夹,使用-maxdepth指定查找深度
find . -maxdepth 1 -type d -empty

查出当前目录下所有空文件夹,并删除。使用管道连接rm命令,用xargs做入参处理
find . -type d -empty | xargs rm -r
find命令可以把匹配到的文件传递给 xargs 命令执行,在使用 find 命令的 -exec 选项处理匹配到的文件时,find将所有匹配到的文件一起传递给 exec 执行。由于有些系统对能够传递给 exec 的命令长度有限制,这样会引起溢出错误。这时可以使用 xargs 命令。

查出当前目录下所有空文件夹,并删除。使用-exec执行rm命令,{}代表前面查找出来的文件,后面必须加;
find . -maxdepth 1 -type d -empty -exec rm -r {} \;

查出当前目录下所有空文件夹,并删除。使用-ok执行rm命令,删除前有提示
find . -maxdepth 1 -type d -empty -ok rm -r {} \;

查出当前目录下所有空文件夹,并删除。使用-delete,无提示,文件目录都可删除
find . -maxdepth 1 -type d -empty -delete

-size 文件大小筛选

-size n[cwbkMG] 文件大小筛选

搜索当前目录下,超过800M大小的文件
find . -type f -size +800M

-atime/ctime/mtime 文件时间筛选

-atime n
-ctime n
-mtime n

atime 即 access time, 即文件被读取或者执行的时间,修改文件是不会改变access time的。
ctime 即 change time, 文件状态改变时间,指文件的i结点被修改的时间,如通过chmod修改文件属性,ctime就会被修改。
mtime 即 modify time, 指文件内容被修改的时间。

atime/ctime/mtime 中的 n 指的是 n×24
+n 表示大于 n
-n 表示小于 n
n 表示等于 n

find . –mtime n 查找文件内容最后一次修改发生在距离当前时间 n×24 小时至 (n+1)×24 小时之间的。
find . –mtime +n 查找文件内容最后一次修改发生在距离当前时间 (n+1)×24 小时之前的。
find . –mtime –n 查找文件内容最后一次修改发生在距离当前时间 n×24 小时以内的。

查找最后更新时间在7天前的文件并删除

查找文件内容最后修改时间在 7 天前的日志文件并删除
find /var/log/myapp.log.* -type f -mtime +7 -exec rm -f {} \;

再配合 crontab 定时任务,可实现 shell 定时删过期日志
crontab -e 填入
20 0 * * * find /var/log/myapp.log.* -type f -mtime +7 -exec rm -f {} \;
每天 0 点 20 删除 7 天前的日志


whereis

whereis 命令用来定位指令的二进制程序、源代码文件和 man 手册页等相关文件的路径。

whereis 命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。

和 find 相比,whereis 查找的速度非常快,这是因为 linux 系统会将 系统内的所有文件都记录在一个数据库文件中,当使用whereis和下面即将介绍的locate时,会从数据库中查找数据,而不是像find命令那样,通 过遍历硬盘来查找,效率自然会很高。 但是该数据库文件并不是实时更新,默认情况下时一星期更新一次,因此,我们在用whereis和locate 查找文件时,有时会找到已经被删除的数据,或者刚刚建立文件,却无法查找到,原因就是因为数据库文件没有被更新。


locate

centos 安装 locate 命令:yum install mlocate

locate 是 Linux 系统中的一个查找(定位)文件的命令,和 find 扫描硬盘不同,locate 是通过生成一个文件和文件夹的索引数据库,一般在 /var/lib/mlocate/mlocate.db 中(有些 Linux 发行版为 slocate:/var/lib/slocate/slocate.db),当用户在执行 loacte 命令查找文件时,它会直接在索引数据库里查找。
所以 locate 比 find 快,locate 的查找并不是实时的,而是以数据库的更新为准,一般是系统自己维护,也可以手工升级数据库,命令为:updatedb默认情况下 updatedb 每天执行一次

若该数据库太久没更新或不存在,在查找文件时就提示:
locate: can not open ‘/var/lib/mlocate/mlocate.db’: No such file or directory

查询 log4j-core 包

# locate *log4j-core*.jar
/data/home/aicu-tob/data/jmeter/apache-jmeter-5.4.1/lib/log4j-core-2.13.3.jar
/data/home/aicu-tob/data/jmeter/apache-jmeter-5.4.1/licenses/log4j-core-2.13.3.jar

which

查看可执行文件的位置。
which 命令的作用是在 $PATH 变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。也就是说,使用 which 命令,就可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的命令。

which 可执行文件名称

用 which 去找出 which

$ which which
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
    /usr/bin/which

竟然会有两个 which ,其中一个是 alias 这就是所谓的『命令别名』,意思是输入 which 会等於后面接的那串命令

找出 cd 这个命令

$ which cd
/usr/bin/which: no cd in (/opt/java/jdk1.7.0_80/bin:/opt/app/scala/scala-2.10.4/bin:/bin:/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/app/spark/spark-1.5.2-bin-hadoop2.6/bin:/opt/app/spark/spark-1.5.2-bin-hadoop2.6/sbin:/opt/app/scala/scala-2.10.4/bin:/home/jboss5/bin)

cd 这个常用的命令竟然找不到啊!为什么呢?这是因为 cd 是bash 内建的命令! 但是 which 默认是找 PATH 内所规范的目录,所以当然一定找不到的!


diff

diff [参数] [文件1或目录1] [文件2或目录2]
例如:

$diff -u hello_old.c hello_new.c > hello.diff

-u表示统一格式输出,其中有+ - !

diff程序的输出被称为补丁 (patch),因为Linux系统中还有一个patch程序,可以根据diff的输出将a.c的文件内容更新为b.c。

diff -r dir1 dir2 比较目录及子目录

# diff -r /usr/lib64/ /matt/lib64/
Only in /usr/lib64/: libgomp.so.1
Only in /usr/lib64/: libgomp.so.1.0.0
Only in /usr/lib64/: libjbig85.so.2.0
Only in /usr/lib64/: libjbig.so.2.0
Only in /usr/lib64/: libjpeg.so.62
Only in /usr/lib64/: libjpeg.so.62.1.0
Only in /usr/lib64/: liblept.so.5
Only in /usr/lib64/: liblept.so.5.0.3
Only in /usr/lib64/: libtesseract.so.4
Only in /usr/lib64/: libtesseract.so.4.0.1
Only in /usr/lib64/: libtiff.so.5
Only in /usr/lib64/: libtiff.so.5.2.0
Only in /usr/lib64/: libtiffxx.so.5
Only in /usr/lib64/: libtiffxx.so.5.2.0
Only in /usr/lib64/: libwebpmux.so.0
Only in /usr/lib64/: libwebpmux.so.0.0.0
Only in /usr/lib64/: libwebp.so.4
Only in /usr/lib64/: libwebp.so.4.0.2

vimdiff

安装 vimdiff
vimdiff 不需要单独安装,首先保证系统中的 diff 命令是可用的,vim 的 diff 模式依赖于 diff 命令,然后安装 vim 就有了 vimdiff 命令。

vimdiff file1 file2 比较两个文本,默认是左右分屏对比
vimdiff -o file1 file2 上下分屏对比

vimdiff

文件编辑

sed

sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。
处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

-n, --quiet, --silent, 使用安静(silent)模式。只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。
-i, 直接修改读取的文件内容,而不是输出到终端。
-r, --regexp-extended 正则扩展

sed -i 直接编辑文件

-i 表示 inplace edit, 就地修改文件
sed -i 's/book/books/g' file, 直接编辑文件选项-i,会匹配file文件中每一行的第一个book替换为books

s/src/dst/ 替换

sed "s/查找串/替换串/" file

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

删除指定的字符

sed 's/a//' 删除每行的第一个字符a
sed 's/a//g' 删除每行中的所有字符a

sed -n 's/test/TEST/p' file, -n选项和p命令一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。

sed 's/[0-9]//g' file 删除文件中每一行中出现的所有数字
sed 's/[a-z]//g' file 删除每一行中出现的小写字符
sed 's/[^a-z]//g' file 删除除了小写字符之外的其他所有字符
sed 's/[a-z][A-Z][0-9]//g' file 删除每一行所有的字母和数字字符

删除行尾/行首的一个字符

^ 匹配行首
$ 匹配行尾

sed 's/.$//' 删除行尾最后一个字符,其中 . 是一个正则表达式字符匹配任何单个字符(除了换行符),$匹配行尾,.$表示行最后一个字符

sed 's/^.//' 删除行首第一个字符,其中 . 匹配任意单个字符,^匹配行首,^.表示行首第一个字符
sed 's/.//' 删除行首第一个字符,因为 sed 命令默认是从开头匹配字符串的,所以使用 . 可以匹配开头的第一个字符。

sed 's/^.//;s/.$//' 同时移除每一行的第一个字符和最后一个字符。sed命令可以结合多个操作指令,每个指令之间通过’;’分割

删除行尾/行首的指定字符

sed 's/^F//' file 如果行首是字符F则删除F,如果行首不是字符F则不做处理
sed 's/,$//' file 如果行尾是字符,则删除,,如果行尾不是字符,则不做处理

删除行首/行尾n个字符

sed 's/...//' file 删除每一行的第一到第三个字符,. 匹配任意单个字符
sed -r 's/.{n}//' file 删除每一行的第一个到第 n 个字符,.{n} 表示.出现4次,即匹配4个任意字符
sed -r 's/.{n}$//' file 删除每一行的最后 n 个字符

删除(指定字符到行尾/行首到指定字符)

sed 's/a.*//' file 删除第一个字符a到行尾的所有字符

# echo 'sdfdfsda12323' | sed 's/a.*//'
sdfdfsd
# echo 'sdfadsfsda12323' | sed 's/a.*//'
sdf

sed 's/.*a//' 删除行首到最后一个字符a

# echo 'sdfadsfsda12323' | sed 's/.*a//'
12323
只保留行首/行尾n个字符

sed -r 's/(.{3}).*/\1/' file 除了每一行的第一到第n个字符外,剩下的都要删除
.{3} 匹配每一行开头3个字符,且用 () 分组;.* 表示匹配任意多个字符。在替换位通过 \1 表示保留第一个分组的内容。
sed -r 's/.*(.{3})/\1/' file 删除每一行所有字符只保留结尾的n个字符

在每行行首行尾添加字符

^ 匹配行首
$ 匹配行尾
sed "s/^/HEAD&/g" test.file 在每行的行首添加串”HEAD”, 其中 ^ 代表行首,& 代表原始行,/g 表示替换所有行
sed "s/$/&TAIL/g" test.file 在每行的行尾添加串”TAIL”, 其中 $ 代表行尾,& 代表原始行,/g 表示替换所有行

逗号替换为换行

sed 's/,/\n/g' file, 所有逗号替换为换行

注意:如果是在 macos 下执行,需要改为

sed 's/,/\
  /g'
全面替换标记/g

默认 sed 只会处理匹配到的第一个字符, 使用后缀 /g 标记会替换每一行中的所有匹配
sed 's/book/books/g' file, 使用后缀 /g 标记会替换每一行中的所有匹配
如果没有 /g 标记,则只有每行第一个匹配的 book 被替换成 books

当需要从 第N处匹配 开始替换时,可以使用 /Ng

echo sksksksksksk | sed 's/sk/SK/2g'
skSKSKSKSKSK

echo sksksksksksk | sed 's/sk/SK/3g'
skskSKSKSKSK

echo sksksksksksk | sed 's/sk/SK/4g'
skskskSKSKSK

sed 's/[aoe]//g' file 删除每行中的所有 ‘a’ 或 ‘o’ 或 ‘e’ 字符

/n处理第n个匹配

默认 sed 只会处理匹配到的第一个字符,/n 可以指定处理匹配到的第几个字符
sed 's/u//2' file 删除每一行匹配到的第 n 个字符u

任意定界符

字符 / 在sed中作为定界符使用,也可以使用任意的定界符:

sed 's:test:TEXT:g'
sed 's|test|TEXT|g'

定界符出现在样式内部时,需要进行转义:

sed 's/\/bin/\/usr\/local\/bin/g'

&匹配查找到的串

sed 's/^192.168.0.1/&localhost/' example
& 符号表示替换换字符串中被找到的部份。所有以 192.168.0.1 开头的行都会被替换成它自已加 localhost, 变成 192.168.0.1localhost


sed -n x,yp filename 截取

1、按行号截取
sed -n x,yp filename,打印文件X行到Y行的内容
例如:
sed -n 5,10p filename,查看文件的第5行到第10行。

2、按时间范围截取:
sed -n '/2021-09-09 00:00:00/,/2021-09-09 01:00:00/'p xxx.log
注意:2021-09-09 01:00:00 如果有多条的话,只能截取到第一条为止。


d命令删除行

sed '2d' example, 删除example文件的第二行。
sed '2,$d' example, 删除example文件的第二行到末尾所有行。
sed '2,5d' example, 删除example文件的第二行到第5行。
sed '$d' example, 删除example文件的最后一行。
sed '/test/'d example, 删除example文件所有包含test的行。


grep

Global Regular Expression Print
是一个强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

grep [-acinv] [--color=auto] '搜寻字符串' filename

选项与参数:
-a :将 binary 文件以 text 文件的方式搜寻数据
-c 计算关键字匹配次数
-i, --ignore-case 忽略大小写的不同,所以大小写视为相同
-n, --line-number 输出行号
-v, --invert-match 反向选择,亦即显示出没有 ‘搜寻字符串’ 内容的那一行!
-r, --recursive 在子目录中递归查找
–color=auto :可以将找到的关键词部分加上颜色的显示。有的系统默认会给grep设一个带有此参数的别名:alias grep=’grep –color=auto’

查看有关nginx的进程
ps -ef | grep nginx

grep的$?结果

$? 表示上一条命令的返回结果,通常0表示成功,非0表示失败。
如果上一条命令是grep,0表示匹配上,非0表示未匹配上。

# echo "masikkk"|grep kkk
masikkk
# echo $?
0

# echo "masikkk"|grep abc
# echo $?
1

在多个文件中查找

同时在文件 file1 file2 file3 中搜索
grep "match pattern" file1 file2 file3

在当前目录下的所有 .log 文件中搜索:
grep pattern *.log

在当前目录及子目录所有文件中查找

grep -rn "pattern" *
-r 是递归查找
-n 是显示行号

从文件末尾搜索

搜索出文件中所有匹配的,然后通过tail命令只打引出最后一行,即得到反向的第一个
grep -n 'something' file.txt | tail -n 1
这种方法需要读取整个文件,当文件过大时很慢

搜索含空格的字符串

\转义空格:
grep Program\ Files file1
或者放到引号内:
grep 'Enter method createUser' /data/log/masikkk/user.log

\转义点
grep 将 . (点)理解为通配符,即任意一个字符,想要精确匹配 ./server 的话需要对 . 进行转义
ps -ef | grep "\./server"

或操作

grep -E '123|abc' filename,找出文件(filename)中包含123或者包含abc的行,-E表示用正则表达式:
egrep '123|abc' filename,用egrep同样可以实现正则表达式匹配
awk '/123|abc/' filename,awk 的实现方式

在log中搜索insertSelective,排除包含0-6 Millis的行,其实用正则写更简单:
grep insertSelective user.log |egrep -v "0 Millis|1 Millis|2 Millis|3 Millis|4 Millis|5 Millis|6 Millis"

与操作

显示既匹配 pattern1 又匹配 pattern2 的行:
grep pattern1 files | grep pattern2

查看包含run.sh但不包含jdk的进程(二次grep筛选):
ps -ef | grep run.sh | grep -v jdk

其他操作示例
grep -i pattern files //不区分大小写地搜索。默认情况区分大小写,
grep -l pattern files //只列出匹配的文件名,
grep -L pattern files //列出不匹配的文件名,
grep -w pattern files //只匹配整个单词,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’),
grep -C number pattern files //匹配的上下文分别显示[number]行,

grep -A -B -C

-A -B -C 后面都跟阿拉伯数字,-A是显示匹配后和它后面的n行。-B是显示匹配行和它前面的n行。-C是匹配行和它前后各n行。

grep -A n file, after,显示匹配结果后n行
grep -B n file, before,显示匹配结果前n行
grep -C n file, context,显示匹配结果前后各n行
例如:
grep -A 4 wikipedia 文件.txt
就是搜索文件,找到匹配“wikipedia”字串的行,显示该行后后面紧跟的4行。


egrep

egrep 命令用于在文件内查找指定的字符串。egrep 执行效果与 grep -E 相似,使用的语法及参数可参照 grep 指令,与 grep 的不同点在于解读字符串的方法。egrep 是用 extended regular expression 法来解读的,而 grep 则用 basic regular expression 语法解读,extended regular expression 比 basic regular expression 的表达更规范。

从 app.log 中查找包含 start 或 stop 关键字的行
egrep “start|stop” app.log

^$ 匹配行首行尾

$匹配换行,匹配 method end+换行
egrep "method end$"

查找 pod 名称中包含 app1 的,以及以 app2- 开头的 pod,^ 表示匹配开头
kubectl get pod -o wide|egrep “app1|^app2-“

匹配日志耗时xx秒以上的

在log中搜索insertSelective,只显示包含 “5位数字 Millis” 的行
grep insertSelective user.log |egrep "[0-9]{5} Millis"

在 app.log 中查找 method1 方法超过10秒的
egrep "method1 proceed cost [0-9]{5} ms" app.log

在 app.log 中查找处理时间在 10 秒到 100 秒之间的日志,即处理时间在5位数到6位数之间的
egrep "proceed cost [0-9]{5,6} ms" app.log
egrep "[0-9]{5,6} millis" app.log -n
查 10 秒到 100 秒的
egrep "featureOneMany takes [0-9]{5,6} ms" abf-search.log.2020-07-23.log
查 20秒 以上的
egrep "featureOneMany takes [2-8][0-9]{4,6} ms" abf-search.log.2020-07-23.log

从 df 结果中排除包含 docker 和 kubelet 的
df -h|egrep -v "docker|kubelet"

匹配目录大小超过10G的

查看磁盘占用 10G 以上的目录
du -sh *|egrep "[0-9]{2,}G"


zgrep

zgrep 命令可以从 gzip 压缩的文件中搜索特定的文本
zgrep “search_string” file.gz

如果系统中没有 zgrep 命令,可以使用 gunzip 和 grep 命令组合来实现同样的功能:
gunzip -c file.gz | grep “search_string”


awk

awk 是一个强大的文本分析工具,其原理简单来说就是把文件逐行的读入,以空格为默认分隔符将每行分割为单词,再进行各种分析处理。
awk 名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。

AWK程序设计语言
https://awk.readthedocs.io/en/latest/index.html

awk 版本

awk 有不同的实现版本,常用的有
1 gawk(GNU AWK), 未作特别说明,一般指 gawk,gawk 是 AWK 的 GNU 版本。

$ awk -W version
GNU Awk 3.1.7

2 nawk(BWK awk 或 BSD awk), FreeBSD 和 MacOS 上使用这个版本

所以,Mac 上的 awk 实现可能和 Linux 上是不同的,有些行为可能会不一致。


awk 程序一次从输入文件的中读取一行内容并把它分割成一个个字段, 默认使用空格或制表符进行字段分割, 也就是说一个字段是一个不包含任何空格或制表符的连续字符序列。

如果一个动作没有任何模式, 这个动作会对所有输入的行进行操作。print 语句用来打印(输出)当前输入的行
{ print } 等于 { print $0 } 会输出所有输入的内容到标准输出。
例如 awk '{print}' awk-test.txt

$N 每行的第 N 个字段
当前输入的行中的第一个字段是 $1, 第二个是 $2, 以此类推。
整个行的内容被定义为 $0, 每一行的字段数量可以不同.
{ print $1, $3 } 打印每行输入中的第一和第三个字段。

NF 每行的字段数量
$NF 每行的最后一列,$(NF-1) 表示倒数第二列
awk '{print NF $0}' awk-test.txt 打印每行的字段数和整行内容。
awk '{print NF, $1, $NF}' awk-test.txt 打印每行的字段数、第一列值、最后一列值

NR 行号
awk '{print NR $0}' awk-test.txt 打印每行的行号和内容

RS Record Separator,记录分隔符,默认的分隔符是\n
自定义RS分割符 echo “111 222|333 444|555 666”|awk ‘BEGIN{RS=”|”}{print $0,RT}’

ORS:Output Record Separate,输出记录分隔符,默认值是\n
FS:Field Separator,字段分隔符
OFS:Out of Field Separator,输出字段分隔符
一行是一条记录,一个单词是一个字段

对数值进行计算
awk '{print $2*$3}' awk-test.txt 计算每行第二列和第三列的乘积,前提是每行第二列和第三列是数值类型。
awk '{print "乘积", $2*$3}' awk-test.txt 对输出加上额外字符


printf 格式化输出

语法 printf(format, value1, value2, ..., valuen)

awk '{printf("第一列 %s 乘积 %.2f\n", $1, $2*$3)}' awk-test.txt 格式化打印第一列和二三列的乘积。

sprintf () 采用和 printf 相同的方式格式化字符串,但是它不会输出格式化后的字符串,而是返回格式化后的字符串。所以,可以将格式化后的字符串赋值给某个变量。
awk 'BEGIN{ name = sprintf("%02d", 3) print name}'

# awk 'BEGIN{name = sprintf("%02d", 3); print name}'
03

if 条件过滤

例1、kubectl get pod -o wide 输出如下,过滤重启次数超过10次的 pod kubectl get pod -o wide |awk '{if ($4 > 10) print $0}'
可以简化为 kubectl get pod -o wide |awk '$4 > 10 {print}'

NAME                       READY   STATUS      RESTARTS   AGE     IP               NODE            NOMINATED NODE   READINESS GATES
consul-slave-2             1/1     Running      4         37d     11.16.39.44      btgpu-node6     <none>           <none>
loki-stack-promtail-6lmtd  1/1     Running     17         232d    10.233.69.153    btgpu-node56    <none>           <none>
redis-cluster6-4           2/2     Running     16         24h     10.233.97.99     btgpu-node50    <none>           <none>

行过滤

1、根据行号筛选
awk ‘NR==2’ a.txt # 筛选出第二行
awk ‘NR>=2’ a.txt # 输出第2行和之后的行

2、根据正则表达式筛选整行
awk ‘/qq.com/‘ a.txt # 输出带有qq.com的行
awk ‘$0 ~ /qq.com/‘ a.txt # 等价于上面命令
awk ‘/^[^@]+$/‘ a.txt # 输出不包含@符号的行
awk ‘!/@/‘ a.txt # 输出不包含@符号的行

3、根据字段来筛选行
awk ‘($4+0) > 24{print $0}’ a.txt # 输出第4字段大于24的行
awk ‘$5 ~ /qq.com/‘ a.txt # 输出第5字段包含qq.com的行

4、将多个筛选条件结合起来进行筛选
awk ‘NR>=2 && NR<=7’ a.txt
awk ‘$3==”male” && $6 ~ /^170/‘ a.txt
awk ‘$3==”male” || $6 ~ /^170/‘ a.txt

5、按照范围进行筛选 pattern1,pattern2{action}
awk ‘NR==2,NR==7’ a.txt # 输出第2到第7行
awk ‘NR==2,$6 ~ /^170/‘ a.txt


for 循环

例1,循环打印2-16号的web日志文件名 awk 'BEGIN { for (i=2;i<=16;i++) printf "log.2023-01-%02d-WEB.log\n", i}'
其中 %02d 表示 2 位整数,左补 0

# awk 'BEGIN { for (i=2;i<=16;i++) printf "log.2023-01-%02d-WEB.log\n", i}'
log.2023-01-02-WEB.log
log.2023-01-03-WEB.log
...
log.2023-01-16-WEB.log

进一步,创建2-16号web日志log文件,awk 'BEGIN { for (i=2;i<=16;i++) printf "log.2023-01-%02d-WEB.log\n", i}' | xargs touch


BEGIN 与 END

提供 BEGIN 和 END 的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。

BEGIN 模块后紧跟着动作块, 紧跟 BEGIN 的 {} 块在 awk 扫描任何输入之前执行 所以它可以在没有任何输入的情况下进行测试。通常使用 BEGIN 来显示变量和预置(初始化)变量,如 OFS,RS 和 FS 等,以及打印标题。
END 不匹配任何的输入文件,但是执行动作块中的所有动作,END之后列出的操作将在扫描完全部的输入之后执行, 常使用 END 来输出最终结果

例1、在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。
awk 'BEGIN {FS=":"; OFS="\t"; ORS="\n\n"} {print $1,$2,$3} test.txt'

例2、打印标题
awk 'BEGIN {print "分钟 qps 平均耗时"}'


加减乘除余

+
-
*
/ 除,结果是浮点数
% 取余

awk 'BEGIN { x = 15; y = 25; print "(x + y) = ", (x + y) }'
awk 'BEGIN { x = 25; y = 15; print "(x - y) = ", (x - y) }'
awk 'BEGIN { x = 25; y = 15; print "(x * y) = ", (x * y) }'
awk 'BEGIN { x = 25; y = 15; print "(x / y) = ", (x / y) }'
awk 'BEGIN { x = 50; y = 20; print "(x % y) = ", (x % y) }'

统计(和/平均/最大/最小)

假如要统计的数字在第1列

1、求和
cat data|awk '{sum+=$1} END {print "Sum = ", sum}'

2、求平均
cat data|awk '{sum+=$1} END {print "Average = ", sum/NR}'

3、求最大值
cat data|awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}'

4、求最小值(min的初始值设置一个超大数即可)
awk 'BEGIN {min = 1999999} {if ($1<min) min=$1 fi} END {print "Min=", min}'

例1、统计下面日志中 method1 和 method2 各自的总耗时

08:13:04.291 [http-nio-8380-exec-67] INFO  com.masikkk.service [342]  - method1 consumes  10 ms, method2 consumes 2 ms
08:13:06.318 [http-nio-8380-exec-22] INFO  com.masikkk.service [342]  - method1 consumes  16 ms, method2 consumes 2 ms
08:13:06.631 [http-nio-8380-exec-60] INFO  com.masikkk.service [342]  - method1 consumes  6 ms, method2 consumes 3 ms
08:13:07.577 [http-nio-8380-exec-38] INFO  com.masikkk.service [342]  - method1 consumes  6 ms, method2 consumes 3 ms

cat xx.log |awk '{method1Sum+=$9; method2Sum+=$13} END {print "method1耗时" method1Sum ",method2耗时" method2Sum}'

5、日志格式如下,统计 分钟平均qps,分钟平均耗时

2021-08-13 20:58:00.195 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44779926 ns
2021-08-13 20:58:00.496 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44479234 ns
2021-08-13 20:59:01.929 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44321052 ns
2021-08-13 20:59:02.944 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44880600 ns
grep "消息处理耗时" mc.log |awk '{print substr($2,1,5)"  "$15}' | awk '{ arr[$1]+=$2} {len[$1]+=1} END { for (key in arr) printf("%s    %s     %s\n", key, len[key]/60,arr[key]/len[key]/1000000)}'

解释:
1、awk '{print substr($2,1,5)" "$15}' 选出分钟列和耗时列
20:58 44779926
20:59 44321052
2、awk '{ arr[$1]+=$2} {len[$1]+=1} END 构造两个数组: arr[] 下标是分钟,内容是对应分钟的耗时总和, len[] 下标是分钟,内容是对应分钟的出现次数, END 表示处理完所有输入行后继续执行后面的语句。
3、最后用 for 语句遍历 arr 数组,key 是每个分钟, len[key]/60 总次数除以60即每秒次数即qps, arr[key]/len[key]/1000000 总耗时除以次数是单次处理的平均耗时
最终结果
20:58 0.0333333 44.6296
20:59 0.0333333 44.6008


match 正则匹配

语法 awk 'match($0,/正则捕获表达式/,a)'{print a[1], a[2]} 表示提取括号捕获的内容到数组 a 中
awk 使用 match 匹配并分组保存到数组中,a[1] 表示数组第一()捕获的内容,以此类推

例 1
例如有如下模式的 nginx 日志
“requestBody”:”{"codes":["code1","code2","code3","code4","code5"],xxxx

提取包含 codes 的行
awk '/codes/ {print $0}' nginx.log

awk 提取 codes 参数数组
awk '{match($0,/.+(codes\\\":)(\[.+\\\"\]).+/,a);print a[1], a[2]}'
正则 /.+(codes\\\":)(\[.+\\\"\]).+/ 表示
.+ 任意字符, () 捕获 codes\"

awk 正则转义

\ (反斜杠)转义字符。
当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。
例如,/a\/\// 将与模式 a// 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。


substr 子串

返回从起始位置起,指定长度之子字符串;若未指定长度,则返回从起始位置到字符串末尾的子字符串。
substr(s,p) 返回字符串s中从p开始的后缀部分,p从1开始
substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分

echo "123" | awk '{print substr($0,1,1)}' 结果为 1

日志格式如下,分析日志看消息处理的 qps

2021-08-13 20:58:00.195 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44779926 ns
2021-08-13 20:58:00.496 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44479234 ns
2021-08-13 20:58:01.929 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44321052 ns
2021-08-13 20:58:02.944 [KafkaConsumerDestination{consumerDestinationName='structured-data-push-topic', partitions=1, dlqName='null'}.container-0-C-1] INFO  c.b.c.mc.server.stream.consumer.AbstractConsumer - 消息处理耗时 StopWatch '消息处理耗时': running time = 44880600 ns

grep "消息处理耗时" mc.log |awk '{print $2}'|awk '{print substr($0,1,length($0)-4)}'|sort|uniq -c

cat xx.log|awk '{print substr($2,1,2)}'|sort|uniq -c 看每个小时的日志数


jq

jq 可以对json数据进行分片、过滤、映射和转换,和sed、awk、grep等命令类似。

https://stedolan.github.io/jq/


wc

利用wc指令我们可以计算文件的行数、单词数,以及该文件的字节数。
若不指定文件名称、或是所给予的文件名为”-“,则wc指令会从标准输入设备读取数据。

wc [-clw] [文件...]

-c或–bytes或–chars 只显示Bytes数。
-l或–lines 只显示行数。
-w或–words 只显示字数。

示例
1、计算testfile文件的统计信息

$ wc testfile
3 92 598 testfile

testfile文件的行数为3、单词数92、字节数598

2、统计redis匹配keys的个数
利用 wc 命令统计 keys 命令结果的行数:
redis-cli -h host -p port -a password keys "prefix-*" | wc -l


tr

translate characters
sed 命令的低配版,可实现很多字符串基本操作。

tr [-cdst][--help][--version][第一字符集][第二字符集]
-c, –complement:反选设定字符。也就是符合 SET1 的部份不做处理,不符合的剩余部份才进行转换
-d, –delete:删除指令字符
-s, –squeeze-repeats:缩减连续重复的字符成指定的单个字符
-t, –truncate-set1:削减 SET1 指定范围,使之与 SET2 设定长度相等

将文件file中出现的”abc”替换为”xyz”
cat file | tr "abc" "xyz" > new_file
注意:凡是在file中出现的”a”字母,都替换成”x”字母,”b”字母替换为”y”字母,”c”字母替换为”z”字母。而不是将字符串”abc”替换为字符串”xyz”

使用tr命令“统一”字母大小写
(小写 –> 大写)
cat file | tr [a-z] [A-Z] > new_file
(大写 –> 小写)
cat file | tr [A-Z] [a-z] > new_file
将输入字符由大写转换为小写:
echo "HELLO WORLD" | tr 'A-Z' 'a-z'

删除文本中的非数字字符
tr -cd "[0-9]"

删除文件file中出现的”Snail”字符
cat file | tr -d "Snail" > new_file
凡是在file文件中出现的’S’,’n’,’a’,’i’,’l’字符都会被删除!而不是紧紧删除出现的”Snail”字符串。

删除文件file中出现的换行’\n’、制表’\t’字符
cat file | tr -d "\n\t" > new_file

删除所有数字0-9:
echo "hello 123 world 456" | tr -d '0-9'

将制表符转换为空格:
cat text | tr '\t' ' '

删除“连续着的”重复字母,只保留第一个
cat file | tr -s [a-zA-Z] > new_file

连续出现的空格(制表符)只保留一个,并用换行符替换空格
cat word_count.txt| tr -s ' \t' '\n'
比如原文本为

masikkk masikkk xx xx x x     kkk kk  kkk
english    count  ? com         masikkk
madaimeng    devgou  com

处理之后成为

masikkk
masikkk
xx
xx
x
x
kkk
kk
kkk
english
count
?
com
masikkk
madaimeng
devgou
com

sort

sort 命令将文件进行排序,并将排序结果标准输出。sort 命令既可以从特定的文件,也可以从 stdin 中获取输入。
sort 将文件/文本的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按 ASCII 码值进行比较,最后将他们按升序输出。
如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序。

sort [-fbMnrtuk] [file or stdin]

选项与参数:
-u, --unique 在输出行中去除重复行
-r, --reverse sort默认的排序方式是升序,如果想改成降序,就加个-r就搞定了。
-o, --output=FILE:将排序后的结果存入制定的文件;

-f :忽略大小写的差异,例如 A 与 a 视为编码相同;
-b :忽略最前面的空格符部分;
-M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
-n :使用『纯数字』进行排序(默认是以文字型态来排序的);
-t :分隔符,默认是用 [tab] 键来分隔;
-k :以那个区间 (field) 来进行排序的意思

输出到源文件
由于sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如
sort filename > newfile
但是,如果你想把排序结果输出到原文件中,用重定向可就不行了。sort -r number.txt > number.txt 源文件会被清空
这个时候,只能用-o选项来指定原文件
sort -r number.txt -o number.txt

linux sort 命令详解
https://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html


uniq

uniq 命令可以统计或去除排序过的文件中的重复行,因此 uniq 经常和 sort 合用。
为了使uniq起作用,所有的重复行必须是相邻的

-c, --count 在每列旁边显示该行重复出现的次数;
-u, --unique 仅显示出一次的行列;
-d, --repeated 仅显示重复出现的行列;

排序后去重,并统计总行数
sort file | uniq | wc

排序之后去除重复行,同时在行首位置输出该行重复的次数
sort testfile | uniq -c
1 friend
3 hello
2 world

仅显示存在重复的行,并在行首显示该行重复的次数
sort testfile | uniq -dc
3 hello
2 world

仅显示不重复的行
sort testfile | uniq -u
friend


文件内容查看

cat

cat命令连接文件并打印到标准输出设备上,cat经常用来显示文件的内容,类似于下的type命令。

注意:当文件较大时,文本在屏幕上迅速闪过(滚屏),用户往往看不清所显示的内容。因此,一般用more等命令分屏显示。为了控制滚屏,可以按Ctrl+S键,停止滚屏;按Ctrl+Q键可以恢复滚屏。按Ctrl+C(中断)键可以终止该命令的执行,并且返回Shell提示符状态。

cat m1 (在屏幕上显示文件ml的内容)
cat m1 m2 (同时显示文件ml和m2的内容)
cat m1 m2 > file (将文件ml和m2合并后放入文件file中)

tac

tac命令就是将文件反向输出,刚好和cat输出相反。
cat test.txt 反向列出test.txt文件的内容


cut

cut命令可以从一个文本文件或者文本流中提取文本列。

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

特定分隔字符分隔列
cut -d'分隔字符' -f fields file

-f 字段范围记法:
N- 从第N个字节、字符、字段到结尾;
N-M 从第N个字节、字符、字段到第M个(包括M在内)字节、字符、字段;
-M 从第1个字节、字符、字段到第M个(包括M在内)字节、字符、字段。

示例文件如下,英文逗号分隔id,姓名,年龄

$ cat id_name_age.txt
2,张三,23
18,李四,18
25,王五,22
31,找六,14

提取第一列

cut -d ',' -f1 id_name_age.txt
2
18
25
31

提取第1,3列

cut -d ',' -f1,3 id_name_age.txt
2,23
18,18
25,22
31,14

path 变量如下,冒号:分隔

$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin

将 PATH 变量取出,我要找出第五个路径。

$ echo $PATH | cut -d':' -f 5
/usr/sbin

将 PATH 变量取出,我要找出第三和第五个路径。

$ echo $PATH | cut -d ':' -f3,5
/usr/bin:/usr/sbin

将 PATH 变量取出,我要找出第三到最后一个路径。

$ echo $PATH | cut -d':' -f3-
/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/.local/bin:/home/ec2-user/bin

将 PATH 变量取出,我要找出第一到第三,还有第五个路径。

$ echo $PATH | cut -d':' -f1-3,5
/usr/local/bin:/bin:/usr/bin:/usr/sbin

tail

tail 显示文件尾部的内容,默认显示尾部后 10 行

tail file 显示文件file的最后10行

-n, --lines=K 显示目标文件的后 k 行,而不是系统默认的后10行

注意:如果表示字节或行数的N值之前有一个”+”号,则从文件开头的第N项开始显示,而不是显示文件的最后N项。N值后面可以有后缀:b表示512,k表示1024,m表示1 048576(1M)。
tail +20 file 显示文件file的内容,从第20行至文件末尾

-f, --follow[={name|descriptor}] 随着文件的增长,显示文件新追加的内容
例如 tail -f error.log 滚动输出 error.log 的最新内容

tailf

tailf 命令打印文件最后10行内容,并且不断刷新
相当于 tail 命令加参数 -f,但当文件不动态增长时不输出内容

tailf与grep结合,只打印想看到的字符串,比如只关心服务器启动日志中的”Started”字符串,说明服务器起来了
tailf serverStart.log | grep Started

tail -f 多个文件

tail -f 1.log 2.log
注意查看多个文件时只能用tail -f,tailf 不行


less

less命令的作用与more十分相似,都可以用来浏览文字档案的内容,不同的是less命令允许用户向前或向后浏览文件,而more命令只能向前浏览。
用less命令显示文件时,用PageUp键向上翻页,用PageDown键向下翻页。
要退出less程序,应按Q键。

翻页:
y/回车键 向前滚动一行
e 向后滚动一行

u 向前滚动半页
d 向后翻半页

f/空格 向前翻页,或者说显示下一页
b 向后翻页,或者说显示上一页

-N 每一行行首显示行号
-s:将连续多个空行压缩成一行显示;
-S:在单行显示较长的内容,而不换行显示;

注意:
使用 vi/vim 读取文件时默认全部加载到内存。但是也可以设置读取到内存中的数据块大小,避免处理大文件时内存吃力。
所以在服务器端一般推荐用 less 查看大文件


more

more 命令,功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上。 more会以一页一页的显示方便使用者逐页阅读,而且还有搜寻字串的功能。

空白键(space)往下翻一页显示
b 键往回(back)翻一页显示

more命令从前向后读取文件,因此在启动时就加载整个文件。


tee

从标准输入读取数据并重定向到标准输出和文件。
主要用在需要同时查看数据内容并输出到文件时。

a, --append 追加到文件中而不是覆盖。

一般用法
cmd | tee res.txt 将 cmd 命令的结果打印到屏幕同时写入 res.txt 文件。


文件处理

ln

ln 命令用来为文件创件连接,连接类型分为硬连接和符号连接两种,默认的连接类型是硬连接。如果要创建符号连接必须使用 -s 选项。
连接有软连接和硬连接(hard link)之分的,软连接(symbolic link)又叫符号连接。符号连接相当于 Windows 下的快捷方式。

当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的目录下用ln命令链接(link)它就可以,不必重复的占用磁盘空间。

ln [-Ffhinsv] source_file [target_file]
ln [-Ffhinsv] source_file ... target_dir

-s, --symbolic 对源文件建立符号连接,即软连接,而非硬连接;
-f, --force 强行删除任何已存在的目标文件

ln –s source target 意思是生成一个软链接 target,连接到源文件或目录 source
例如:sudo ln -sf /usr/bin/python3.7 /usr/bin/python 之后使用 python 命令就相当于使用 python3.7
再比如 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 常用于设置时区

这里有两点要注意:
第一,ln 命令会保持每一处链接文件的同步性,也就是说,不论你改动了哪一处,其它的文件都会发生相同的变化;
第二,ln 的链接又分为软链接和硬链接两种,软链接就是 ln –s source target, 它只会在你选定的位置上生成一个文件的镜像,不会占用磁盘空间,硬链接 ln ** **, 没有参数-s, 它会在你选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。

I节点
I节点是 UNIX 内部用于描述文件特性的数据结构。我们通常称I节点为文件索引结点(信息结点)。I节点含有关于文件的大部分的重要信息,包括文件数据块在磁盘上的地址,每一个I节点有它自己的标志号,我们称为文件顺序号。
I节点包含的信息

  1. 文件类型
  2. 文件属主关系
  3. 文件的访问权限
  4. 文件的时间截.

软/硬链接与I节点
硬连接不管有多少个,都指向的是同一个I节点,会把结点连接数增加,只要结点的连接数不是0,文件就一直存在,不管你删除的是源文件还是连接的文件,只要有一个存在,文件就存在(其实也不分什么源文件连接文件的,因为他们指向都是同一个 I节点)。当你修改源文件或者连接文件任何一个的时候,其他的文件都会做同步的修改。
软链接不直接使用i节点号作为文件指针,而是使用文件路径名作为指针。所以 删除连接文件对源文件无影响,但是删除源文件,连接文件就会找不到要指向的文件。软链接有自己的inode,并在磁盘上有一小片空间存放路径名.


touch

touch命令有两个功能:一是用于把已存在文件的时间标签更新为系统当前的时间(默认方式),它们的数据将原封不动地保留下来;二是用来创建新的空文件。


dd

dd 命令用于复制文件并对原文件的内容进行转换和格式化处理。
dd命令常用于磁盘备份

参数:
if=文件名 输入文件名,缺省为标准输入。即指定源文件。
of=文件名 输出文件名,缺省为标准输出。即指定目的文件。
ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
bs=bytes 同时设置读入/输出的块大小为 bytes 个字节。块大小可指定单位。
cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
count=blocks 仅拷贝blocks个块,块大小等于 ibs/bs 指定的字节数。
conv=conversion:用指定的参数转换文件。

块大小可以使用的计量单位表
字节(1B) c
字节(2B) w
块(512B) b
千字节(1024B) k
兆字节(1024KB) M
吉字节(1024MB) G

备份/恢复磁盘数据

1、将本地的 /dev/hdb 整盘备份到 /dev/hdd
dd if=/dev/hdb of=/dev/hdd

2、将 /dev/hdb 全盘数据备份到指定路径的 image 文件
dd if=/dev/hdb of=/root/image

3、将备份文件恢复到指定盘
dd if=/root/image of=/dev/hdb

4、备份磁盘开始的512个字节大小的MBR信息到指定文件
dd if=/dev/hda of=/root/image count=1 bs=512
count=1指仅拷贝一个块;bs=512指块大小为512个字节。

5、销毁磁盘数据
dd if=/dev/urandom of=/dev/hda1
注意:利用随机的数据填充硬盘,在某些必要的场合可以用来销毁数据。

创建swap分区文件

第一步:创建一个大小为256M的文件(块大小1024字节,拷贝262144个块):
dd if=/dev/zero of=/swapfile bs=1024 count=262144
第二步:把这个文件变成swap文件:
mkswap /swapfile
第三步:启用这个swap文件:
swapon /swapfile
第四步:编辑/etc/fstab文件,使在每次开机时自动加载swap文件:
/swapfile swap swap default 0 0

生成一个5GB的随机文件

dd if=/dev/urandom of=random.txt bs=1M count=5000
if=/dev/urandom 指定了输入文件为 /dev/urandom,这是一个提供随机字节的设备文件。
of=random.txt 指定了输出文件为 random.txt。
bs=1M:设置每次读写的块大小为 1MB。
count=5000:设置只读写 5000 个块,因此总计会生成一个 5000MB(约等于 5GB)的文件。


tar

tar 命令用来打包文件,注意 tar 命令不一定就是压缩或解压文件,带 -z 参数时才压缩和解压,不带 -z 则只是打包(archive),比如将多个文件/目录打包到一个 archive 档案文件
http://www.cnblogs.com/li-hao/archive/2011/10/03/2198480.html
主选项:
-c, --create 创建新的档案文件。如果用户想备份一个目录或是一些文件,就要选择这个选项。相当于打包。
-x, --extract, --get 从档案文件中释放文件。相当于拆包。
-t 列出档案文件的内容,查看档案包中有哪些文件
注意:主选项 c/x/t 互斥,只能存在一个

辅助选项:
-z, --gzip 是否同时具有 gzip 的属性?亦即是否需要用 gzip 压缩或解压? 一般格式为xx.tar.gz或xx. tgz
-v, --verbose 压缩的过程中显示文件
-f, --file=ARCHIVE 使用档名,请留意,在 f 之后要立即接档名 不要再加其他参数!

-k, --keep-old-files 遇到同名文件时保留旧文件,会报错。解压缩时,如果目标目录中已经存在同名文件会直接覆盖,如果不想覆盖可以加 -k 参数
-C, --directory=DIR 指定解压目录(此目录必须已存在),这个选项用在解压缩,用 -C 参数指定解压到的目录
-T, --files-from=FILE 从文件中读取压缩文件列表,常用于文件过多导致出现 Argument list too long 错误时
-p, --preserve-permissions, --same-permissions 使用原文件的原来属性(属性不会依据使用者而变)

Argument list too long tar压缩文件过多

待压缩的文件过多时,提示 -bash: /bin/tar: Argument list too long
解决:
1、生成文件清单到 manifest 文件
find . -name '*.json' -print >manifest
但是这一步 find 命令也会报错 Argument list too long, 解决方法是根据扩展名或文件名结构,分段 find 筛选,比如
(1) 把 json 导入清单: find . -name '*.json' -print > manifest
(2) 把 png 导入清单: find . -name '*.png' -print >> manifest 注意第二次要用追加输出

2、使用 -T, --files-from=FILE 参数从文件清单 manifest 中读取待压缩文件列表
tar -czvf file.tar.gz -T manifest

tar -czvf name.gz dir 压缩

压缩tar -czvf
将当前目录下所有.txt文件打包并压缩归档到文件this.tar.gz,我们可以使用
tar -czvf this.tar.gz ./*.txt

tar -xzvf name.gz 解压到当前目录

解压tar -xzvf
将当前目录下的this.tar.gz中的文件解压到当前目录我们可以使用
tar -xzvf this.tar.gz ./

tar -xzvf name.gz -C dir 解压到指定目录

解压到指定目录-C
使用 tar 的 -C dir 参数可以做到将文件解压缩到其他指定目录(此目录必须已存在),例如:
tar -xvf file2.tar -C /home/usr2
而tar不用-C dir参数时是无法做到的

tar -tf name.gz 查看包中的文件列表

各种压缩文件的解压方法

不同后缀压缩文件的解压和压缩命令都不一样,总结如下:
1、.tar 用 tar –xvf 解压
2、.gz 用 gzip -d或者gunzip 解压
3、.tar.gz和.tgz 用 tar –xzf 解压
4、.bz2 用 bzip2 -d或者用bunzip2 解压
5、.tar.bz2用tar –xjf 解压
6、.Z 用 uncompress 解压
7、.tar.Z 用tar –xZf 解压
8、.rar 用 unrar 解压
9、.zip 用 unzip 解压


pigz

pigz(parallel implementation of gzip) 多线程压缩文件。

pigz 只是用多线程实现压缩,压缩后的文件格式还是原来的,pigz 压缩的文件依然可以使用普通 tar -xvf 命令解压

虽然 pigz 使用多线程进行压缩,但解压是单线程的,因为解压缩过程无法并行化。然而,pigz会创建额外的线程用于读取、写入和校验计算,这在某些情况下可以加速解压缩过程。
https://github.com/madler/pigz/issues/36

yum 安装 pigz

yum install pigz
$ which pigz
/usr/bin/pigz

安装后拷贝 /usr/bin/pigz 到其他未联网的 linux 机器可直接使用

参数:
-p, --processes n 压缩时使用的核心数量,默认使用所有核心
-k, --keep 压缩后保留源文件
-d, --decompress 解压缩
-l, --list ll列出压缩输入的内容
-0 to -9, -11 压缩机别,-6 是默认的压缩机别,-9 压缩率最高,但是速度慢,-1 压缩率最低,速度最快

例1、压缩 app.log,保留原文件,不加 -k 的话默认会删除原文件。
pigz -k app.log
执行后得到 app.log.gz 文件

例2、pigz -l 查看文件的压缩率

# ./pigz -l app.log.gz 
compressed   original reduced  name
   3938241  106402207   96.3%  app.log

例3、解压单个文件 app.log.gz,-k 保留原文件
pigz -k -d app.log.gz

pigz 可作为 tar 命令的参数使用

tar 命令参数
-I, --use-compress-program=COMMAND 指定压缩工具,可以写入压缩工具的完整路径
tar –use-compress-program=pigz -cvf d.tgz *

pigz 压缩/解压文件夹

pigz 压缩文件夹
pigz 没有压缩文件夹的选项,只可以压缩单个文件,但可以和 tar 命令一起使用来压缩文件夹
tar -cf - /path-to-dir | pigz -k > dir.tar.gz
tar cf - /path-to-dir | pigz -k > dir.tar

pigz 解压文件夹
pigz -dc dir.tar|tar xf -

tar -I pigz -xvf compressed_file.tar.gz

https://stackoverflow.com/questions/14980048/how-to-decompress-with-pigz


zip

-r 将指定的目录下的所有子目录以及文件一起处理
-a 将文件转成ASCII模式
-F 尝试修复损坏的压缩文件
-h 显示帮助界面
-m 将文件压缩之后,删除源文件
-n 特定字符串 不压缩具有特定字尾字符串的文件
-o 将压缩文件内的所有文件的最新变动时间设为压缩时候的时间
-q 安静模式,在压缩的时候不显示指令的执行过程
-S 包含系统文件和隐含文件(S是大写)
-t 日期 把压缩文件的最后修改日期设为指定的日期,日期格式为mmddyyyy

将 /home/wwwroot/xahot/ 这个目录下所有文件和文件夹打包为当前目录下的 xahot.zip
zip –r xahot.zip /home/wwwroot/xahot

-d 从压缩文件内删除指定的文件。
删除 jar 包中的指定 class
zip -d log4j-core-2.5.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
删除 war 包中的指定目录
zip -d xxx.war "WEB-INF/config/**"

gunzip 解压.gz文件

-c 将解压后的文件输出到标准输出设备

gunzip xx.gz

unzip 解压.zip文件

-d <目录> 指定文件解压缩后所要存储的目录;

mismatching “local” filename

unzip 解压zip提示:
mismatching “local” filename xxx, continuing with “central” filename version
原因是压缩文件中有中文命名的文件,解压出现了乱码
解决:
unzip -qO UTF-8 xxx.zip ,指定为utf-8格式

unzip解压java war包

unzip app.war -d app

例如:将压缩文件 text.zip 在当前目录下解压缩
unzip text.zip

将压缩文件text.zip在指定目录/tmp下解压缩。
unzip text.zip -d /tmp


工具

sz/rz

sz 和 rz 命令都是在远程服务器上执行的。

SecureCRT 设置上传下载文件保存路径
options -> session -> Xmodem/Zmodem -> upload / download

rz本地到远程

保证当前处于远程服务器上,输入 rz 命令后会打开一个选择文件的对话框,选择文件后就开始上传,会上传到当前目录。
单独用rz会有两个问题:上传中断、上传文件变化(md5不同),解决办法是上传时用rz -be,并且去掉弹出的对话框中“Upload files as ASCII”前的勾选
-b 以二进制方式,默认为文本方式。(Binary (tell it like it is) file transfer override.)
-e 对所有控制字符转义。(Force sender to escape all control characters; normally XON, XOFF, DLE, CR-@-CR, and Ctrl-X are escaped.)

sz远程到本地

保证当前处于远程服务器上,输入 sz filename 命令后会弹出窗体让我们选择要保存的地方。
下载一个文件:sz filename
下载多个文件:sz filename1 filename2
下载目录dir下的所有文件(不包含dir下的文件夹):sz dir/*

yum 安装lrzsz

yum install lrzsz

mac安装并配置rzsz

brew install lrzsz
默认安装目录 /usr/local/Cellar/lrzsz/0.12.20_1

在 /usr/loal/bin 目录下创建两个文件
vim iterm2-recv-zmodem.sh
vim iterm2-send-zmodem.sh

将文件写好后保存好,使用如下命令添加权限
chmod +777 iterm2-*
配置好配置文件之后,开始对iTerm2进行配置
点击 iTerm2 的设置界面 Perference-> Profiles -> Default -> Advanced -> Triggers 的 Edit 按钮,加入以下配置

Regular expression: rz waiting to receive.\*\*B0100
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-send-zmodem.sh

Regular expression: \*\*B00000000000000
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-recv-zmodem.sh

iterm2-recv-zmodem.sh:

#!/bin/bash
# Author: Matt Mastracci (matthew@mastracci.com)
# AppleScript from http://stackoverflow.com/questions/4309087/cancel-button-on-osascript-in-a-bash-script
# licensed under cc-wiki with attribution required
# Remainder of script public domain

osascript -e 'tell application "iTerm2" to version' > /dev/null 2>&1 && NAME=iTerm2 || NAME=iTerm
if [[ $NAME = "iTerm" ]]; then
    FILE=`osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")"`
else
    FILE=`osascript -e 'tell application "iTerm2" to activate' -e 'tell application "iTerm2" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")"`
fi

if [[ $FILE = "" ]]; then
    echo Cancelled.
    # Send ZModem cancel
    echo -e \\x18\\x18\\x18\\x18\\x18
    sleep 1
    echo
    echo \# Cancelled transfer
else
    cd "$FILE"
    /usr/local/bin/rz -E -e -b
    sleep 1
    echo
    echo
    echo \# Sent \-\> $FILE
fi

iterm2-send-zmodem.sh:

#!/bin/bash
# Author: Matt Mastracci (matthew@mastracci.com)
# AppleScript from http://stackoverflow.com/questions/4309087/cancel-button-on-osascript-in-a-bash-script
# licensed under cc-wiki with attribution required
# Remainder of script public domain

osascript -e 'tell application "iTerm2" to version' > /dev/null 2>&1 && NAME=iTerm2 || NAME=iTerm
if [[ $NAME = "iTerm" ]]; then
    FILE=`osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose file with prompt "Choose a file to send"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")"`
else
    FILE=`osascript -e 'tell application "iTerm2" to activate' -e 'tell application "iTerm2" to set thefile to choose file with prompt "Choose a file to send"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")"`
fi
if [[ $FILE = "" ]]; then
    echo Cancelled.
    # Send ZModem cancel
    echo -e \\x18\\x18\\x18\\x18\\x18
    sleep 1
    echo
    echo \# Cancelled transfer
else
    /usr/local/bin/sz "$FILE" -e -b
    sleep 1
    echo
    echo \# Received $FILE
fi

scp 远程拷贝

scp src-file user@host:dst-file 将本地文件上传到远程主机

-i identity_file 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh
-P port 指定端口号,scp端口号和ssh端口号相同

1、从服务器下载文件到本地
scp user@host/ip:/remote_path/filename ~/filename
/remote_path/filename 是远程文件名
~/filename 是本地文件名

使用密钥
scp -i ~/.ssh/id_rsa user@host/ip:/home/user/file.txt ~/local_destination

默认使用 22 端口,可用大写 -P 指定端口
scp -i ~/.ssh/id_rsa -P port username@host/ip:/home/user/file.txt ~

2、上传本地文件到服务器
scp ~/local_path/local_filename user@host/ip:/remote_path
根据提示输入用户密码

使用秘钥
scp -i ~/.ssh/id_rsa filename user@host/ip:~

默认使用22端口,可用大写 -P 指定端口
scp -i ~/.ssh/id_rsa -P port filename user@host/ip:~

3、从服务器下载整个目录
scp -r username@host/ip:/remote_path/remote_dir/ ~/local_destination

4、上传目录到服务器
scp -r ~/local_dir username@host/ip:/remote_path/remote_dir


rsync 远程文件同步

rsync(remote sync) 是一个常用的 Linux 应用程序,用于文件同步。

它可以在本地计算机与远程计算机之间,或者两个本地目录之间同步文件(但不支持两台远程计算机之间的同步)。它也可以当作文件复制工具,替代 cp,mv.scp 命令。

-r 表示递归,即包含子目录。-r 是必须的,否则 rsync 运行不会成功。
-a 参数可以替代-r,除了可以递归同步以外,还可以同步元信息(比如修改时间、权限等)。由于 rsync 默认使用文件大小和修改时间决定文件是否需要更新,所以-a比-r更有用。
-n 参数模拟命令执行的结果,并不真的执行命令。
-v 参数则是将结果输出到终端,这样就可以看到哪些内容会被同步。
--exclude 排除匹配的文件

mysql设置主从复制前,把 master 的 data 拷贝到 slave 上,排除 binlog 文件

rsync -av --exclude="mysql-bin.*" /data/software/mysql-5.7.19/data/ root@127.0.0.1:/data/software/mysql-5.7.19/data/


man

获取帮助信息
方法一:命令 --help, 例如 rm --help
方法二:man 命令, 例如 man rm,给出详细的使用手册
方法三:info 命令, 例如 info rm

安装c函数库手册:
yum install man-pages

安装c++函数库手册:
yum insall libstdc++-docs


xargs

xargs 命令(eXtended ARGuments)是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。
它擅长将标准输入数据转换成命令行参数,xargs 能够处理管道或者 stdin 并将其转换成特定命令的命令参数。
xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。
xargs 的默认命令是 echo,空格是默认定界符,这意味着通过管道传递给 xargs 的输入需要包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。
xargs 是构建单行命令的重要组件之一。

-n num 后面加次数,表示命令在执行的时候一次用的 argument 的个数,默认是用所有的。
-n1 可以将参数按空格拆成多行给后续命令,-n2 将参数2个一行传给后续参数。

# echo "abc 123"|xargs
abc 123
# echo "abc 123"|xargs -n1
abc
123
# echo "abc 123 111"|xargs -n2
abc 123
111

-i 参数默认的前面输出用 {} 代替
-I 指定其他替换字符串, 这个字符串在 xargs 扩展时会被替换掉
例如把 find 找到的所有文件拷贝到上层目录
find . -name "file" | xargs -i cp {} ..
或者
find . -name "file" | xargs -I [] cp [] ..

查找当前目录及所有子目录中的java文件 拷贝到 new 子目录中
find . -type f -name "*.java" | xargs -I {} mv {} ./new

多行输入单行输出:
cat test.txt | xargs
其中test.txt是包含空格、tab、换行分割的多行文件

查出当前目录下所有空文件夹,并删除。使用管道连接rm命令,用xargs做入参处理
find . -type d -empty | xargs rm -r
find命令可以把匹配到的文件传递给 xargs 命令执行,在使用 find 命令的 -exec 选项处理匹配到的文件时,find将所有匹配到的文件一起传递给 exec 执行。由于有些系统对能够传递给 exec 的命令长度有限制,这样会引起溢出错误。这时可以使用 xargs 命令。

查找并删除当前目录及其子目录下的所有.DS_Store 文件:
find . -name '*.DS_Store' -type f -delete
find . -name '.DS_Store' | xargs rm -r

查找 frgate 相关的进程并kill
ps aux|grep frgate|awk '{print $2}'|xargs kill -9

查找用户 masikkk 的 nginx 相关的进程并kill, grep -v grep是为了把grep命令自己去掉
ps -ef|grep nginx|grep -v grep|grep masikkk|awk '{print $2}'|xargs kill -9

redis 模糊匹配kyes并删除,在可远程连接redis的跳板机或本地机器上执行:
redis-cli -h redis-host keys "prefix-*" | xargs redis-cli -h redis-host del

强制删除所有名称包含 “feature-user” 的本地分支。
git branch |grep 'feature-user' |xargs git branch -D


md5sum

md5sum 命令采用MD5报文摘要算法(128位)计算和检查文件的校验和。一般来说,安装了Linux后,就会有md5sum这个工具,直接在命令行终端直接运行。

mac上直接 md5 命令即可

md5 xx.file 获取文件的 md5
echo "string" | md5 获取字符串的 md5

$ md5sum *.sql
de019b1e3b957cf81a404253dbc8e3f9  1.update_user.sql
36acdb26b9c2235657dcd0b0293b5a32  2.insert_user.sql

date

Linux date命令可以用来显示或设定系统的日期与时间,在显示方面,使用者可以设定欲显示的格式,格式设定为一个加号后接数个标记

-d<字符串> 显示字符串所指的日期与时间。字符串前后必须加上双引号。
-s<字符串> 根据字符串来设置日期与时间。字符串前后必须加上双引号。
-u 显示GMT。

在显示方面,使用者可以设定欲显示的格式,格式设定为一个加号后接数个标记
%Y 年份(以四位数来表示)。
%m 月份(以01-12来表示)。
%d 日期(以01-31来表示)。
%H 小时(以00-23来表示)。
%M 分钟(以00-59来表示)。
%S 秒(以本地的惯用法来表示)。

date +”%Y-%m-%d”
2021-05-07

-s设置时间
date -s //设置当前时间,只有root权限才能设置,其他只能查看。
date -s 20080523 //设置成20080523,这样会把具体时间设置成空00:00:00
date -s 01:01:01 //设置具体时间,不会对日期做更改
date -s “01:01:01 2008-05-23″ //这样可以设置全部时间
date -s “01:01:01 20080523″ //这样可以设置全部时间
date -s “2008-05-23 01:01:01″ //这样可以设置全部时间
date -s “20080523 01:01:01″ //这样可以设置全部时间

-d时间加减操作:
date +%Y%m%d # 显示年月日
date -d “+1 day” +%Y%m%d # 显示前一天的日期
date -d “-1 day” +%Y%m%d # 显示后一天的日期
date -d “-1 month” +%Y%m%d # 显示上一月的日期
date -d “+1 month” +%Y%m%d # 显示下一月的日期
date -d “-1 year” +%Y%m%d # 显示前一年的日期
date -d “+1 year” +%Y%m%d # 显示下一年的日期


watch

将命令的输出结果输出到标准输出设备,多用于周期性执行命令/定时执行命令
-n, --interval <secs> 指定 watch 更新间隔秒数,默认 2 秒更新一次
-d, --differences[=<permanent>] 高亮变动区域,-d=cumulative 选项会把变动过的地方(不管最近的那次有没有变动)都高亮显示出来。
-t, --no-title 关闭watch命令在顶部的时间间隔

watch -n 1 date 一秒打印一次时间

watch -n 1 "netstat -anp|grep 8080" 一秒打印一次端口连接

Mac 安装 watch 命令
brew install watch


ntpdate 时间同步

为了避免主机时间因为长期运作下所导致的时间偏差,进行时间同步(synchronize)的工作是非常必要的。Linux系统下,一般使用ntp服务器来同步不同机器的时间。一台机器,可以同时是ntp服务器和ntp客户机。在网络中,推荐使用像DNS服务器一样分层的时间服务器来同步时间。

同步时间,可以使用ntpdate命令,也可以使用ntpd服务

ntpdate ip/host
但这样的同步,只是强制性的将系统时间设置为ntp服务器时间。如果cpu tick有问题,只是治标不治本。所以,一般配合cron命令,来进行定期同步设置。比如,在crontab中添加:
0 12 * * * * /usr/sbin/ntpdate 192.168.0.1
这样,会在每天的12点整,同步一次时间。ntp服务器为192.168.0.1。


base64

对文件、标准输入进行 base64 编解码,并打印到标注输出

-d, –decode 解码数据
-i, –ignore-garbag 解码时忽略非字母字符
-w, –wrap=字符数 在指定的字符数后自动换行(默认为76),0 为禁用自动换行
–version 显示版本信息并退出

如果没有指定文件,或者文件为”-“,则从标准输入读取。

数据以 RFC 3548 规定的 Base64 字母格式进行编码。 解码时,输入数据(加密流)可能包含一些非有效 Base64 字符的新行字符。可以尝试用 –ignore-garbage 选项来恢复加密流中任何非 base64 字符。

base64 从标准输入中读取数据,按Ctrl+D结束输入。将输入的内容编码为base64字符串输出。

echo "str" | base64 将字符串 str+换行 编码为base64字符串输出。
echo -n "str" | base64 将字符串str编码为base64字符串输出,最后没有换行。注意与上面的差别。

base64 file 从指定的文件file中读取数据,编码为base64字符串输出。

base64 -d 从标准输入中读取已经进行base64编码的内容,解码输出。

base64 -d -i 从标准输入中读取已经进行base64编码的内容,解码输出。加上-i参数,忽略非字母表字符,比如换行符。

echo "str" | base64 -d 将base64编码的字符串str+换行 解码输出。
echo -n "str" | base64 -d 将base64编码的字符串str解码输出,最后没有换行。注意与上面的差别。

base64 -d file 从指定的文件file中读取base64编码的内容,解码输出。

删除base64末尾的换行符

base64 face.png 生成的base64串末尾有个换行符,如果再接md5命令,可能和java生成的md5不同

可以使用 tr 删除末尾的换行符
base64 face.png |tr -d “\n”|md5 去掉base64末尾换行符


crontab

Linux crontab 是用来定期执行程序的命令。
当安装完成操作系统之后,默认便会启动此任务调度命令。
crond 每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。
注意:新创建的 cron 任务,不会马上执行,至少要过 2 分钟后才可以,当然你可以重启 cron 来马上执行。

crontab [ -u user ] { -l | -r | -e }

-u user 是指设定指定 user 的时程表,这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话,就是表示设定自己的时程表。
-e 执行文字编辑器来设定时程表,内定的文字编辑器是 VI, 如果你想用别的文字编辑器,则请先设定 VISUAL 环境变数来指定使用那个文字编辑器(比如说 setenv VISUAL joe)
-l 列出当前用户的时程表
-r 删除目前的时程表

时间格式如下:
minute hour day month week command分 时 日 月 周 命令
minute: 表示分钟,可以是从0到59之间的任何整数。
hour:表示小时,可以是从0到23之间的任何整数。
day:表示日期,可以是从1到31之间的任何整数。
month:表示月份,可以是从1到12之间的任何整数。
week:表示星期几,可以是从0到7之间的任何整数,这里的0或7代表星期日。
command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。

*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    +----- 星期中星期几 (0 - 7) (星期天 为0)
|    |    |    +---------- 月份 (1 - 12)
|    |    +--------------- 一个月中的第几天 (1 - 31)
|    +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59)

在以上各个字段中,还可以使用以下特殊字符:
星号 * 代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
逗号 , 可以用逗号隔开的值指定一个可选值列表,例如,“1,2,5,7,8,9”
中杠 - 可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
正斜线 / 可以用正斜线指定时间的间隔频率,例如 0-23/2 表示每两小时执行一次。同时正斜线可以和星号一起使用,例如 */10 如果用在minute字段,表示每十分钟执行一次。

例如

0 */2 * * * /sbin/service httpd restart  意思是每两个小时重启一次apache

50 7 * * * /sbin/service sshd start  意思是每天7:50开启ssh服务

50 22 * * * /sbin/service sshd stop  意思是每天22:50关闭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  意思是每月的1、11、21、31日是的6:30执行一次ls命令

crontab 未执行/执行了但命令未生效

脚本单独执行没问题,但通过 crontab 触发执行不生效,看 /var/log/cron 日志定时任务本身是执行了的,但命令未生效。
这种情况多数都是因为环境变量问题,手动执行任务时是在当前 shell 环境下进行的,程序能够找到环境变量,而系统自动执行任务调度时,是不会加载任何环境变量的。因此需要在 shell 脚本中提供所有必要的路径和环境变量。

注意下面几点:
1、脚本中涉及文件路径时写绝对路径,不要写相对路径
2、需要用到 PATH 等环境变量时,执行脚本前通过 source 命令引入环境变量,例如:

0 */2 * * * source /etc/profile && sh /home/my/mycron.sh

查看crontab执行日志

默认情况下,crontab 定时任务的日志在 /var/log/cron* 文件中

ls /var/log/cron*
/var/log/cron  /var/log/cron-20210815  /var/log/cron-20210823  /var/log/cron-20210829  /var/log/cron-20210906

tail -f /var/log/cron 可查看当前的 crontab 日志

tail /var/log/cron
Sep  8 14:01:01 lightsail run-parts(/etc/cron.hourly)[21536]: finished 0anacron
Sep  8 15:01:01 lightsail CROND[18869]: (root) CMD (run-parts /etc/cron.hourly)
Sep  8 15:01:01 lightsail run-parts(/etc/cron.hourly)[18869]: starting 0anacron
Sep  8 15:01:01 lightsail run-parts(/etc/cron.hourly)[18878]: finished 0anacron
Sep  8 16:01:01 lightsail CROND[16190]: (root) CMD (run-parts /etc/cron.hourly)
Sep  8 16:01:01 lightsail run-parts(/etc/cron.hourly)[16190]: starting 0anacron
Sep  8 16:01:01 lightsail run-parts(/etc/cron.hourly)[16199]: finished 0anacron
Sep  8 17:01:01 lightsail CROND[13420]: (root) CMD (run-parts /etc/cron.hourly)
Sep  8 17:01:01 lightsail run-parts(/etc/cron.hourly)[13420]: starting 0anacron
Sep  8 17:01:01 lightsail run-parts(/etc/cron.hourly)[13429]: finished 0anacron

如何实现秒级crontab

比如想 10 秒执行一次,开 5 个每分钟执行的定时任务,分别先 sleep 10s/20s/30s/40s/50s 即实现了每隔 10 秒执行一次。

# crontab -l
* * * * *  sleep 10; command
* * * * *  sleep 20; command
* * * * *  sleep 30; command
* * * * *  sleep 40; command
* * * * *  sleep 50; command

上一篇 SoapUI使用笔记

下一篇 pgAdmin使用笔记

阅读
评论
62.7k
阅读预计260分钟
创建日期 2015-11-03
修改日期 2024-02-28
类别
目录
  1. 性能监测与优化
    1. top
      1. 交互命令
      2. top zxmc
      3. VIRT虚拟内存/RES常驻内存
      4. VSZ虚拟内存/RSS常驻内存
      5. top结果中load过高可能原因?
      6. top -Hp pid 查看进程的线程信息
      7. mac中的top命令
      8. 实例解析
    2. uptime
    3. vmstat
    4. iostat
    5. free
    6. pmap
    7. lsof
      1. 查看文件被哪些进程打开了
      2. 查看所有进程的文件打开数
      3. -u 查看某用户打开的文件
      4. -c 查看某个命令打开的文件
      5. -p 查看某进程号打开的文件
      6. -i 查看网络连接
      7. +L1 查看已删除但未释放磁盘的文件
      8. lsof: no pwd entry for UID 33
      9. 返回结果解析
    8. lscpu
      1. 查看cpu核数
    9. fuser
    10. time
    11. strace
  2. 网络相关
    1. netstat
      1. 查看某端口占用情况
      2. netstat结果中的TCP连接状态
      3. 查看已建立的连接数
      4. -c 持续查看连接
    2. ss
      1. ss -anp 查看端口占用
      2. ss -s 查看socket统计
    3. traceroute
    4. dig
    5. ping
    6. tcpping
    7. telnet
      1. MAC 安装 telnet
      2. 退出 telnet
      3. telnet 测试 TRACE/TRACK 方法
    8. Linux 测试端口连通性
      1. telnet 测试端口连通性
      2. ssh -v -p 测试端口连通性
      3. curl 测试端口连通性
      4. wget 测试端口连通性
    9. ifconfig
    10. hostname
    11. nslookup
    12. hostnamectl
    13. ip
      1. ip r查看默认网关
    14. route
      1. 查看机器是否有默认网关
    15. curl
      1. curl 读 json 文件
      2. curl 默认不支持https
      3. curl 测试 TRACE/TRACK 方法
      4. option –data-raw: is unknown
      5. -s grep curl 结果
      6. curl 超时时间设置
    16. wget
      1. curl与wget的区别
      2. wget 发送POST json请求
      3. wget 设置header
    17. nc netcat
      1. 端口扫描
      2. 聊天服务器
      3. 远程拷贝文件
    18. socat
      1. 操作文件
      2. 端口监听与转发
      3. 端口转发
      4. socat 将容器内端口暴露到宿主机
    19. tcpdump
  3. Shell内建命令
    1. sh
    2. env
    3. set
      1. set -e 失败立即结束
      2. set -x 打印出命令本身
      3. set -u 遇到未定义变量时报错
    4. unset
    5. declare
    6. export
    7. readonly
    8. echo
    9. tput
    10. source
    11. exec
    12. command
      1. command -v 检查命令是否存在
    13. eval
    14. shopt
      1. zsh中没有shopt命令
    15. alias
      1. 在shell脚本中使用alias
    16. history
      1. history个数设置(上下方向键无法查看历史记录)
      2. history命令显示时间
    17. kill
      1. SIGTERM(-15)默认信号可被处理
      2. SIGKILL(-9)立即结束
      3. SIGINT(-2)等于Ctrl+C
      4. 常用信号名称
      5. 批量kill -9
      6. 僵尸进程(defunct)
    18. pkill
    19. killall
    20. trap
    21. wait
    22. ulimit
  4. 内核与模块管理
    1. sysctl
      1. 修改linux内核参数的3种方式
      2. systemd-sysctl.service
      3. sysctl.d内核参数配置文件目录
    2. lsmod
      1. 判断模块是否已加载到内核
    3. modprobe
    4. uname
      1. 查看Linux内核版本
      2. 查看Linux系统版本
        1. 查看CentOS系统版本
        2. 查看RedHat系统版本
        3. 查看Alpine系统版本
        4. 查看Debian系统版本
    5. dmesg 查看内核日志
    6. journalctl 查看服务日志
      1. 限定日志所能占用的最高容量
      2. 查看进程被谁kill了
  5. 文件系统与磁盘
    1. sync
    2. swapon
    3. swapoff
    4. mkswap
      1. 添加交换分区
      2. 添加交换文件
      3. 删除交换文件
    5. du
      1. du -sh * 当前目录下文件和目录大小
    6. df
    7. lsblk
    8. fdisk
    9. parted
      1. 如何查看磁盘是否分区?
      2. 查看磁盘分区表
      3. 使用parted命令进行磁盘分区
    10. smartctl 查看磁盘型号
    11. losetup
    12. mount
      1. 修改 /home 目录挂载的磁盘
    13. umount
    14. lsscsi
      1. 如何判断是否固态硬盘
    15. systemd-detect-virt 判断物理机/虚拟机
  6. 用户和工作组管理
    1. su
    2. sudo
    3. id
    4. useradd
    5. userdel
    6. passwd 修改口令
    7. gpasswd
      1. 修改用户的工作组
    8. usermod
    9. This account is currently not available
    10. last
      1. last reboot 查看系统重启次数和时间
    11. chroot
    12. chsh
    13. w
    14. who
    15. users
    16. whoami
    17. who am i
    18. last
  7. 进程和作业管理
    1. ps
    2. pstree
    3. pgrep
    4. nohup
      1. nohup和&
      2. nohup后命令依然停止
      3. ctrl+z放到后台并挂起
      4. There are stopped jobs.
    5. jobs
      1. exit 时提示 There are stopped jobs
    6. fg
    7. bg
  8. 目录基本操作
    1. cd
      1. No space left on device
      2. 根目录和家目录
    2. pwd
    3. dirname
    4. basename
    5. cp
    6. mv
    7. rename
    8. rm
      1. rm: Argument list too long
    9. mkdir
    10. ls
      1. 目录下文件过多导致ls卡住
  9. 文件权限属性设置
    1. stat
      1. linux系统的文件时间
    2. chmod
    3. chown
    4. chgrp
    5. file
  10. 文件查找和比较
    1. find
      1. 忽略查询报错
      2. 查找空目录并删除
      3. -size 文件大小筛选
      4. -atime/ctime/mtime 文件时间筛选
      5. 查找最后更新时间在7天前的文件并删除
    2. whereis
    3. locate
    4. which
    5. diff
    6. vimdiff
  11. 文件编辑
    1. sed
      1. sed -i 直接编辑文件
      2. s/src/dst/ 替换
        1. 删除指定的字符
        2. 删除行尾/行首的一个字符
        3. 删除行尾/行首的指定字符
        4. 删除行首/行尾n个字符
        5. 删除(指定字符到行尾/行首到指定字符)
        6. 只保留行首/行尾n个字符
        7. 在每行行首行尾添加字符
        8. 逗号替换为换行
        9. 全面替换标记/g
        10. /n处理第n个匹配
        11. 任意定界符
        12. &匹配查找到的串
      3. sed -n x,yp filename 截取
      4. d命令删除行
    2. grep
      1. grep的$?结果
      2. 在多个文件中查找
      3. 在当前目录及子目录所有文件中查找
      4. 从文件末尾搜索
      5. 搜索含空格的字符串
      6. 或操作
      7. 与操作
      8. grep -A -B -C
    3. egrep
      1. ^$ 匹配行首行尾
      2. 匹配日志耗时xx秒以上的
      3. 匹配目录大小超过10G的
    4. zgrep
    5. awk
      1. awk 版本
      2. print 简单输出
      3. printf 格式化输出
      4. if 条件过滤
      5. 行过滤
      6. for 循环
      7. BEGIN 与 END
      8. 加减乘除余
      9. 统计(和/平均/最大/最小)
      10. match 正则匹配
      11. awk 正则转义
      12. substr 子串
    6. jq
    7. wc
    8. tr
    9. sort
    10. uniq
  12. 文件内容查看
    1. cat
    2. tac
    3. cut
    4. tail
      1. tailf
      2. tail -f 多个文件
    5. less
    6. more
    7. tee
  13. 文件处理
    1. ln
    2. touch
    3. dd
      1. 备份/恢复磁盘数据
      2. 创建swap分区文件
      3. 生成一个5GB的随机文件
    4. tar
      1. Argument list too long tar压缩文件过多
      2. tar -czvf name.gz dir 压缩
      3. tar -xzvf name.gz 解压到当前目录
      4. tar -xzvf name.gz -C dir 解压到指定目录
      5. tar -tf name.gz 查看包中的文件列表
      6. 各种压缩文件的解压方法
    5. pigz
      1. pigz 可作为 tar 命令的参数使用
      2. pigz 压缩/解压文件夹
    6. zip
    7. gunzip 解压.gz文件
    8. unzip 解压.zip文件
      1. mismatching “local” filename
      2. unzip解压java war包
  14. 工具
    1. sz/rz
      1. rz本地到远程
      2. sz远程到本地
      3. yum 安装lrzsz
      4. mac安装并配置rzsz
    2. scp 远程拷贝
    3. rsync 远程文件同步
    4. man
    5. xargs
    6. md5sum
    7. date
    8. watch
    9. ntpdate 时间同步
    10. base64
      1. 删除base64末尾的换行符
    11. crontab
      1. crontab 未执行/执行了但命令未生效
      2. 查看crontab执行日志
      3. 如何实现秒级crontab

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论