命令全称
使用 man
man 可以查看”系统命令/系统调用函数/glibc库函数” 等等共9类内容, 例如 man lsof
第一行是 “LSOF(8)”, 表示是第8类, man man
第一行是”man(8)” 表示man 是第8类, 也可以看到所有9类 “manual”, 如下:
- 系统命令
- 系统调用,一般是对应的C封装函数;所有系统调用的函数在调用发生时都会进入内核空间执行
- 各种库函数手册,例如glibc,pthread库API等,如果是非C库,则会标注出对于的链接选项
- 特殊设备文件,例如zero, mem等
- 文件格式手册,描述Linux支持的各种文件系统以及对于的C接口结构,如vfat/iso
- 游戏程序文档
- 其它的各种各样不在前边分类的文档(8/9除外)
- 系统管理员命令,一般仅供root用户使用,如cron/useradd等
- Linux内核相关部分的手册,一般情况很少用到,这一节就没有intro介绍页
man ascii
: 该命令用来查看 ASC II表man malloc
: 查看malloc用法, 如果显示 “No manual entry for malloc”, 则需要安装 “man-pages”:yum -y install man-pages
ps, top, free, vmstat
vmstat
, sar
, iostat
, iotop
@link:: Linux.03.命令行-Performance
sort, uniq, wc, cut
sort
参数:- -t 指定分隔符
- -n 按数字大小排序, 如果不加-n默认是ASCII码排序
- -r 倒序
- -k 1,5 指定按哪一列排序, 默认是从第N列到行尾,
-k4
指定按第四列排序
例:
按进程VSS内存排序:ps aux | tr -s " " | sort -nrk 5 | cut -d " " -f 1,2,5,6,11- | more
分隔符为”:”的文件按照第5列数值排序:cat file | sort -t : -nrk 1,5
uniq
只能去除相邻行的重复, 所以一般跟sort
联用.- -c: 去重+统计次数
- sort联用:
cat /proc/cpuinfo | grep 'physical id' | sort | uniq | wc -l
wc
:- -l: 统计行数
- -w: 统计单词数
cut
用来显示行中的指定部分, 分隔符用-d 参数(如果不加-d参数则分隔符是制表符), 取出第几列用-f 参数(从1开始),
例:who | cut -d ' ' -f 2
注: cut通常和其他命令一起使用, 用来处理其他命令的输出, 但实际情况下很多命令的分隔符并不统一, 所以用 awk比 cut更方便:
ls -l | awk '{print $9}'
chmod, chown, chgrp
通过ls -l
查看文件属性:
chmod [-R] xyz 文件或目录名
: xyz三个数字即 owner/group/other的 rwx属性之和 (r=4, w=2, x=1)chmod 640 file1
// 给user读写权限, group读权限, other无权限chmod u=rw,g=r,o= file1
// 同chmod 640
chmod -R o-r /home/*
// 把other的读权限都去掉. chmod支持+
,-
,=
符号.
chown [–R] 属主名 文件名
orchown [-R] 属主名:属组名 文件名
chgrp [-R] 属组名 文件名
注: 目录的x权限指可以cd到这个目录, 目录的r权限指可以遍历目录下的文件,
父级目录和子文件的权限互不影响, 例如用户有父级目录的x权限, 但目录下的文件不会继承x权限, 但是如果要执行目录下文件, 前提是能切到父级目录, 意味着父级目录要有x权限
ln
- 创建软链接:
ln -s src target
// 记住ln ... as ...
- 创建硬链接:
ln src target
- 软链接vs硬链接:
- 允许对目录创建软链接,硬链接不可以
- 可以跨文件系统创建软链接, 硬链接不可以
- 删除源文件, 软链接将失效, 硬链接仍保留删除前源文件内容
gzip, bzip2, tar
压缩与读压缩命令:gzip -v file1 # 压缩为gz格式
bzip2 -z file1 # 压缩为bz2格式
zcat file1.gz # 不解压读取gz
bzcat file1.bz2 # 不解压读取bz2
gzip -d file1.gz # 解压gz
bzip2 -d file1.bz2 # 解压bz2
注意: gzip压缩后不保留源文件, bzip2必须加
-k
参数才保留源文件
打包与解包:tar cvzf file1 file1.tar.gz # 打包为 tar.gz
tar cvjf file1 file1.tar.bz2 # 打包为 tar.bz2
tar xvzf file1.tar.gz
tar xvjf file1.tar.bz2
where, which, locate
功能和which类似, 也是一种查找, 区别在于locate搜索的是数据库/var/lib/locatedb所以速度更快, 例如locate _vimrc
sed, awk
@ref: sed & awk & grep
find, grep, ack
- find:
- 按时间查找, 可用参数有:
-mmin
以分钟为单位,-mtime
以天为单位, 后面的数字+
表示比该时间更早,-
表示该时间之后-当前,- 查找N天之前更早的:
find . -mtime +3 -name '*.log'
- 查找N天前~当前时刻的:
find . -mtime -3 -name '*.log'
- 查找N天之前更早的:
- 在当前目录及其子目录下查找符号链接文件:
find -type l
- 在当前目录及其子目录下查文件夹:
find -type d
- 在当前目录查找普通文件:
find -type f
- 在root目录下及其最大3层深度的子目录中查找:
find / -max-depth 3 -name log
- 查找特定文件并ls列出:
find -name *.java -exec ls -l {} \;
注意exec的参数必须以”分号”结束,分号还要加转义符.解释:{}
是前面find找到的文件,-exec
后面的参数后面跟的是command命令, 它的终止是以;
为结束标志的, 所以这句命令后面的”分号”是不可缺少的, 考虑到各个系统中分号会有不同的意义, 所以前面加反斜杠. 参考 Using semicolon (;) vs plus (+) with exec in find - Stack Overflow- shell的内建命令
-exec
将并不启动新的shell, 而是用要被执行命令替换当前的shell进程, 并且将老进程的环境清理掉, 而且exec命令后的其它命令将不再执行. 以新的进程去代替原来的进程, 但进程的PID保持不变.
- 与xargs配合使用:
find find -name *.java | xargs rm -f
- 按时间查找, 可用参数有:
文件的 atime, mtime,ctime
atime: 文件访问时间, 用touch
,vi
等命令都会修改这个时间
ctime: 文件元数据(所属人,读写权限..)chown
,chmod
都会…
mtime: 文件内容修改时间, ps修改了文件内容, 文件元数据也会变化ls -l
列出来的是ctime
命令stat fileName
返回如下
grep:
- 查找某个文件:
grep "Invalid user" /var/log/auth.log
- 查找多个Word:
grep -E "word1|word2"
- 在某个目录下递归查找:
grep -irn "xxx" /dir
- 与
find
一起使用:find . -name "*.css" | xargs grep "monospac"
grep = globally search for regular expression and print out // @ref: https://www.geeksforgeeks.org/grep-command-in-unixlinux/
- 查找某个文件:
ack:
ack xxxx dir/log1
: 在指定文件里搜索xxxack --java xxxx
: 在java文件里搜索xxxack -i xxx
: 不区分大小写ack -w xxx
: 全词匹配ack 'http:|https:' **/*.md
who, w, whoami, last
w
- Show who is logged on and what they are doing.who
- show who is logged onwhoami
- print effective useridwho am i
- When a user logs in as a root across the network, both the commandwhoami
andwho am i
will show you root. However, when a user abc logs in remotely
and runssu – root
,whoami
will show root whereaswho am i
will show abclast
: 获取每个用户登录的持续时间. 该记录保存在:/var/log/wtmp
lsof, fuser
fuser:
列出哪个进程在使用文件: fuser /etc/filenames
lsof:
- 常用参数:
-p 进程id
-i :端口号
-P
: 默认情况lsof会显示 “端口名字” 而不是 “数字类型的端口号” (如果此端口号有名字的话),-P
可以指定显示数字端口号, 而不是名字
- 用法示例:
- 查找已被删除但硬盘空间不释放的文件:
lsof |grep delete
, 这个文件的innode链接被移除了, 但还没有被删掉 - 某个端口:
lsof -i TCP:8080
orlsof -i :80
, -i是列出listening的sock,If -i4 or -i6 is specified with no following address, only files of the indicated IP version - 某个进程:
lsof -p PID
- 查看所有活动状态的网络服务: lsof -i
- 查看某个用户打开的文件:
lsof -u ^root
, 或者lsof | grep ^root
- 查找已被删除但硬盘空间不释放的文件:
文件实际上是一个指向inode的链接, inode链接包含了文件的所有属性, 比如权限和所有者, 数据块地址(文件存储在磁盘的这些数据块中). 当你删除(rm)一个文件, 实际删除了指向inode的链接, 并没有删除inode的内容. 进程可能还在使用. 只有当inode的所有链接完全移去, 然后这些数据块将可以写入新的数据.
Example: lsof返回数据如下:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME |
lsof | awk '{process[$1]++;} END{for(key in process) printf("%s:%d\n", key, process[key])}'
// 每个进程打开的文件数lsof | awk '{if($8 == "TCP") opened_tcp++} END{print opened_tcp }'
//打开TCP连接数量lsof | awk '{opened_type[$5]++} END{ for(key in opened_type) printf("%s : %d\n", key, opened_type[key])}'
// 打开文件按TYPE统计
du, df, fdisk
- du:
- 查看当前子目录大小:
du -h --max-depth=1
- 当前目录文件按大小排序:
du -s * | sort -n | tail
- 查看当前子目录大小:
- df: (英文全拼:disk free) 显示文件系统的使用情况 & 挂载点
- -h:
--human-readable
- -h:
- fdisk: 创建和维护分区表
- -l:列出所有分区表
-exec, xargs
xargs的作用一般等同于大多数Unix shell中的反引号, 但更加灵活易用, 并可以正确处理输入中有空格等特殊字符的情况. 对于经常产生大量输出的命令如find、locate和grep来说非常有用: file * |grep ASCII | cut -d":" -f1 |xargs ls -l
- -exec查找并grep:
find . -name "*.php" -exec grep -in "string" {} \;
最后的\;
是-exec的结束标识 - xargs:
find . -name "*.php" | xargs grep -in "string"
ulimit
- 查看所有的限制:
ulimit -a
- set 最大打开文件句柄数:
ulimit -n 65535
, 查看当前值ulimit -n
- set 最大进程数:
ulimit -u 32768
, 查看当前值ulimit -u
- set 线程栈的大小:
ulimit -s 10240
- set core文件大小:
ulimit -c xxx
, 不限制core的大小:ulimit -c unlimited
- set 最大打开文件句柄数:
ulimit起作用的范围是当前Shell, 并不是作用于”当前用户”, 如要对”用户”做限制, 则需要修改系统文件
/etc/security/limits.conf
umask
umask命令用来设置限制新建文件权限的掩码。当新文件被创建时,其最初的权限由文件创建掩码决定。用户每次注册进入系统时,umask命令都被执行, 并自动设置掩码mode来限制新文件的权限。用户可以通过再次执行umask命令来改变默认值,新的权限将会把旧的覆盖掉。
umask 022
: 用户权限为755umask 077
: 用户权限为700
su, sudo
su:
su
: 切换到root用户, 切换之前的环境变量一并被带到了新shell里;su - user_name
: 切换用户, 切换之后的环境变量会改变为新用户的,su -
同su - root
- 例:
su - root -c commands
, 执行完commands之后自动切换会原来的用户.
- 例:
sudo:
sudo
是受限制的su, 两个命令的最大区别是:sudo
命令需要输入当前用户的密码,su
命令需要输入 root 用户的密码。sudo -s cmd
: 执行cmd命令, 如果是sudo -s
则会启动一个可交互shell, 有点类似su
,- 通过修改
/etc/sudoer
配置哪些用户具有执行sudo的权限, sudo命令能继承哪些环境变量也是在/etc/sudoer
中配置的.
export & 环境变量
VAR=hello
$VAR scope is restricted to the shell;export VAR=hello
makes the $VAR available to child processes;
每个进程的环境变量可以在/proc/$PID/evnrion
查看.
sh, exec, source的区别
source
和 点命令.
是一样的, 不会启动子shell, 不需要script有可执行权限, script里定义的变量也会被导入当前的shell环境../script
启动子shell, script里的变量不会被带进当前环境, 相当于fork
, 需要脚本有x权限sh ./script
先启动了一个子shell, 子shell继承父shell的环境变量, 但子shell里新建变量、改变变量 不会被带回父shell, 除非用export VAR="xxx"
exec cmd
产生了新的进程, 新进程会关闭当前shell的进程, 新的进程继承了原shell的PID号, 原shell剩下的内容不会执行,
顺序执行
多命令顺序执行:
- 分号(
;
): 顺序执行,命令之间不存在关系,互不影响- 例
ls; date; cd /user; pwd
- 例
- 逻辑与(
&&
): 只有第一条命令成功执行,才会执行第二条命令- 例
cd ~/dir && git commit -am "u" && git pull && git push
- 例
- 逻辑或(
||
): 第一条成功执行,第二条不执行; 第一条非正确执行,第二条才会执行
kill
APUE.03a.进程nohup
并不是所有的程序都像 Nginx, Redis, httpd一样提供守护进程, 保证在关闭终端会话后正常运行.
如果终端会话关闭,那么程序也会被关闭。为了能够后台运行,那么我们就可以使用nohup:
nohup cmd &
: 后台运行cmd, 程序运行的输出信息放到当前目录的 nohup.out 文件中去nohup command > myout.log 2>&1 &
: 后台运行cmd, 并指定输出的文件
nohup的原理也很简单,终端关闭后会给此终端下的每一个进程发送
SIGHUP
信号,而使用nohup运行的进程则会忽略这个信号,因此终端关闭后进程也不会退出。
命令重定向
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件: 文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
输出重定向
将输出重定向到 file |
有关
command >out.file 2>&1 &
的解释(注意文件描述符和重定向符号之间不能有空格):
最后的&
表示后台运行;
为什么是2>&1
而不是2>1
? 这样做会直接输出文件名为1的文件;>outfile
和2>&1
的顺序可以交换吗? 不可以,command 2>&1 >out.file
, 先2>&1
的意思是 stderr输出到 stdout, 此时的 stdout是输出到终端的, stderr也就被输出到终端, 然后>out.file
是把 stdout输出到文件, 但是此时 stderr还是输出到终端的;
输入重定向
将 file的内容作为标准输入 |
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
其他用法
- 创建一个空文件, 除了touch还可 :
> file
- 用ssh远程执行本地脚本, 不用scp拷贝 :
ssh root@host bash < /local/xxx.sh
<(COMMAND)
可以作为一个文件 :diff /etc/host <(ssh remote cat /etc/hosts)
trap
- 脚本内执行
java -jar ...
命令, 通过$!
获得子进程ID - 脚本执行
wait 子进程ID
- 如下
_term() { |