Linux.01::常用命令行

命令全称

=> Linux.01a.常用命令行全称速记

使用 man

man 可以查看”系统命令/系统调用函数/glibc库函数” 等等共9类内容, 例如 man lsof 第一行是 “LSOF(8)”, 表示是第8类, man man 第一行是”man(8)” 表示man 是第8类, 也可以看到所有9类 “manual”, 如下:

  1. 系统命令
  2. 系统调用,一般是对应的C封装函数;所有系统调用的函数在调用发生时都会进入内核空间执行
  3. 各种库函数手册,例如glibc,pthread库API等,如果是非C库,则会标注出对于的链接选项
  4. 特殊设备文件,例如zero, mem等
  5. 文件格式手册,描述Linux支持的各种文件系统以及对于的C接口结构,如vfat/iso
  6. 游戏程序文档
  7. 其它的各种各样不在前边分类的文档(8/9除外)
  8. 系统管理员命令,一般仅供root用户使用,如cron/useradd等
  9. 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查看文件属性:
linux-file-rwx

  • 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] 属主名 文件名 or chown [-R] 属主名:属组名 文件名
  • chgrp [-R] 属组名 文件名

注: 目录的x权限指可以cd到这个目录, 目录的r权限指可以遍历目录下的文件,
父级目录和子文件的权限互不影响, 例如用户有父级目录的x权限, 但目录下的文件不会继承x权限, 但是如果要执行目录下文件, 前提是能切到父级目录, 意味着父级目录要有x权限

ln

  • 创建软链接: ln -s src target // 记住 ln ... as ...
  • 创建硬链接: ln src target
  • 软链接vs硬链接:
    • 允许对目录创建软链接,硬链接不可以
    • 可以跨文件系统创建软链接, 硬链接不可以
    • 删除源文件, 软链接将失效, 硬链接仍保留删除前源文件内容

理解 Linux 的硬链接与软链接

gzip, bzip2, tar

linux_compress_cmd

压缩与读压缩命令:

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'
    • 在当前目录及其子目录下查找符号链接文件: 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: 在指定文件里搜索xxx
    • ack --java xxxx: 在java文件里搜索xxx
    • ack -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 on
  • whoami - print effective userid
  • who am i - When a user logs in as a root across the network, both the command
  • whoami and who am i will show you root. However, when a user abc logs in remotely
    and runs su – root, whoami will show root whereas who am i will show abc
  • last: 获取每个用户登录的持续时间. 该记录保存在: /var/log/wtmp

lsof, fuser

fuser:
列出哪个进程在使用文件: fuser /etc/filenames

lsof:

  • 常用参数:
    • -p 进程id
    • -i :端口号
    • -P : 默认情况lsof会显示 “端口名字” 而不是 “数字类型的端口号” (如果此端口号有名字的话), -P可以指定显示数字端口号, 而不是名字
  • 用法示例:
    • 查找已被删除但硬盘空间不释放的文件: lsof |grep delete, 这个文件的innode链接被移除了, 但还没有被删掉
    • 某个端口: lsof -i TCP:8080 or lsof -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
init 1 root cwd DIR 8,1 4096 2 /
crond 4621 root txt REG 8,5 64096 151941 /usr/sbin/crond
crond 4621 root DEL REG 8,1 115 /lib64/libnss_files-2.12.so
nginx 42544 root 194u unix 0xffff880012b9a080 0t0 510761950 socket
nginx 42544 root 195u unix 0xffff8800cbb99cc0 0t0 510761952 socket
java 27672 root 66u IPv4 41351930 0t0 TCP *:56494 (LISTEN)
  • 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
  • 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

ulimit起作用的范围是当前Shell, 并不是作用于”当前用户”, 如要对”用户”做限制, 则需要修改系统文件/etc/security/limits.conf

umask

umask命令用来设置限制新建文件权限的掩码。当新文件被创建时,其最初的权限由文件创建掩码决定。用户每次注册进入系统时,umask命令都被执行, 并自动设置掩码mode来限制新文件的权限。用户可以通过再次执行umask命令来改变默认值,新的权限将会把旧的覆盖掉。

  • umask 022: 用户权限为755
  • umask 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 > file

# 将输出追加重定向到 file
command >> file

# 将文件描述符为n的文件重定向到 file
n>file

# 将文件描述符为 n 的文件以追加的方式重定向到 file
n>>file

# 将文件描述符为 m 和 n 的内容合并,注意
n>&m

# 将文件描述符为 m 和 n 的内容合并, 一并输出到 file
command > file m>&n

有关 command >out.file 2>&1 & 的解释(注意文件描述符和重定向符号之间不能有空格):
最后的& 表示后台运行;
为什么是 2>&1 而不是 2>1 ? 这样做会直接输出文件名为1的文件;
>outfile2>&1 的顺序可以交换吗? 不可以, command 2>&1 >out.file , 先2>&1 的意思是 stderr输出到 stdout, 此时的 stdout是输出到终端的, stderr也就被输出到终端, 然后 >out.file是把 stdout输出到文件, 但是此时 stderr还是输出到终端的;

输入重定向

# 将 file的内容作为标准输入
command < file

# 将 infile的内容作为标准输入, 标准输出写入 outfile
command < infile > outfile

# Here Document 式重定向输入, 将定界符(下面例子中的EOF没有特殊含义, 可以自定义界定符)之间的作为stdin
command << EOF
hello
world
EOF

默认情况下,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() {
kill -TERM "$child_pid"
wait "$child_pid"
}
trap _term SIGTERM

java -Dspring.profiles.active=test \
-Dserver.port=9013 \
-jar wallet-console-2.0.0.jar &

child_pid=$!
wait "$child_pid"

网络相关命令

Linux.02.网络命令

常用配置文件

Linux.04.系统配置