linux usage

工具

  • iftop 展示网络连接及速度

文件及目录

按大小排序打印文件

1
2
3
$ ls -lSh   # -S: 按大小排序; -h: human readable
$ ls -lShr # -r: 倒序
$ ls -lShrR # -R: 递归列出子文件夹

在特定文件内查找内容

grep

1
$ grep -inr --include pom.xml apollo . # i: 忽略大小写; r: 递归; n: 行号

vim

1
:vimgrep /apollo/g **/pom.xml 

递归查找特定文件[夹]

1
2
3
4
5
# command
find <search-pa>

# 示例
$ find . -name '\.idea'

删除

1
$ find . -name '\.idea' | xargs rm  -r

目录栈

dirs : 查看当前目录栈

  • -v : 列出目录及其序号
  • -l : 列出目录全名
  • -c : 清空目录栈

pushd :改变目录并将原目录压入栈

popd : 修改当前目录为栈顶目录并将栈顶目录出栈

1
2
3
4
5
6
7
8
9
10
$  ~ dirs
~
$ ~ pushd Downloads
~/Downloads ~
$ Downloads dirs
~/Downloads ~
$ Downloads popd
~
$ ~ dirs
~

递归查看从根至某个路径的权限

1
2
3
4
5
6
7
8
9
$ namei -om /path/to/check

# 示例
$ namei -om /home/wii/share/
f: /home/wii/share/
dr-xr-xr-x root root /
drwxr-xr-x root root home
drwx------ wii wii wii
drwxrwxrwx wii wii share

如果一个用户需要访问一个目录,应该有访问其父路径的权限。

获取脚本路径

脚本所在文件夹

支持使用 source 引用脚本。

1
2
3
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
# or
SCRIPT_DIR=$(readlink -f $0 | xargs dirname)

查看软连文件大小

1
2
# -L 
ls -lhL

从文件中提取指定行

1
2
3
4
sed '{NUM}q;d' file

# 实例
sed '10q;d' file

用户

创建用户

1
2
3
4
5
6
7
$ useradd -d <home-dir> -s <login-shell> -g <GROUP> username

# 示例
$ useradd -d /home/wii -s /bin/bash -g wheel wii

# 添加到 sudoers 组
$ usermod -aG wheel <user-name>

免密登录

1
2
3
4
5
6
7
8
9
10
11
12
13
# 以配置 主机A 免密登录 主机B 为例
# [A] 生成密钥文件(~/.ssh/id_rsa, ~/.ssh/id_rsa.pub), 如果已生成可略过
$ ssh-keygen -t rsa -C <email>

# [A] 拷贝密钥
$ ssh-copy-id -i ~/.ssh/id_rsa.pub <user@remote-host>

# [B] 修改目录权限
$ chmod 700 ./.ssh
$ chmod 600 ~/.ssh/authorized_keys

# [A] 登录
$ ssh <remote-host>

切换至 root 用户

1
2
3
4
5
6
7
8
9
# sudo -i / sudo -s / sudo bash / sudo su

Summary of the differences found
corrupted by user's
HOME=/root uses root's PATH env vars
sudo -i Y Y[2] N
sudo -s N Y[2] Y
sudo bash N Y[2] Y
sudo su Y N[1] Y

root 权限无需密码

1
2
3
4
5
6
7
8
9
10
# 修改权限
sudo chmod u+w /etc/sudoers
#
sudo visudo

# 修改 /etc/sudoers,添加下面内容
## 注意:
### 1. 先把用户加到 wheel 组 (命令: sudo usermod -aG wheel <username>)
### 2. 放到 "%wheel ALL=(ALL) ALL " 的下面, 所以: 最好放到文件最后
<username> ALL=(ALL) NOPASSWD: ALL

ssh 无需确认添加指纹信息

1
2
3
4
5
6
ssh -o StrictHostKeyChecking=no

# 比如
The authenticity of host '192.168.6.10 (<no hostip for proxy command>)' can't be established.
ECDSA key fingerprint is SHA256:Zag81PG/YLKsybs3QAdsea4Sd4gJvwaa+c49X6ts3buM.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

切换用户

1
su <user>

进程

批量杀死进程

1
2
3
4
5
6
# 按进程名称
$ ps aux | grep <process-name> | awk '{print $2}' | xargs kill -9
# 按端口
$ lsof -t -i:8200 | awk '{print $2}' | xargs kill -9
# 杀死后台线程
$ kill $(jobs -p)

滚动日志

1
kill -USR1 <pid>

排查进程无故 killed

1
$ dmesg -T| grep -E -i -B100 'killed process'

查看进程工作路径

1
2
3
4
5
6
7
8
# pwdx
pwdx <pid>

# lsof
lsof -p <PID> | grep cwd

# proc
readlink -e /proc/<PID>/cwd

按进程名称查找进程 id

1
2
pgrep {process-name}     # 进程名 like 搜索
pgrep -x {process-name} # 进程名精确匹配

等待进程结束

1
$ wait {pid}

等待后台线程结束

1
$ wait $(jobs -p)

设备

磁盘

磁盘读写监控

1
$ iotop -o 

参数

1
-o 仅显示有速度的进程

磁盘测速

1
$ sudo hdparm -Tt /dev/sda

Shell

排查 PATH 问题

1
bash --login -x  # 命令行输入, 打印每个命令的执行, 可以调试 PATH 设置

bash 读取配置文件顺序

  • /etc/profile
  • $HOME/.bash_profile
  • $HOME/.bash_profile 不存在则读 $HOME/.bash_login
  • $HOME/.bash_login 不存在则读 $HOME/.profile

tail 多个远程文件

1
2
3
4
# 在一台机器执行
ssh -n user@host1 'tail -f /path/to/file' &
ssh -n user@host2 'tail -f /path/to/file' &
ssh -n user@host3 'tail -f /path/to/file' &

日期

1
2
3
4
5
# 当前年月日
$ date '+%Y-%m-%d'
2021-11-06
$ date '+%Y%m%d-%H%M%S'
20220916-110256
  • %D – Display date as mm/dd/yy
  • %Y – Year (e.g., 2020)
  • %m – Month (01-12)
  • %B – Long month name (e.g., November)
  • %b – Short month name (e.g., Nov)
  • %d – Day of month (e.g., 01)
  • %j – Day of year (001-366)
  • %u – Day of week (1-7)
  • %A – Full weekday name (e.g., Friday)
  • %a – Short weekday name (e.g., Fri)
  • %H – Hour (00-23)
  • %I – Hour (01-12)
  • %M – Minute (00-59)
  • %S – Second (00-60)

Tips

打印保存在变量内的变量值

1
2
3
4
5
6
7
8
9
10
11
# ${!ref}
$ real="hello"
$ ref=real
$ echo ${!ref}
hello

# 环境变量可以也可以使用 printenv
$ export real="hello"
$ ref=real
$ printenv $ref
hello

ssh

端口转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ssh -i <secret> -L <port-local>:<ip>:<port-remote> <user>@<host>

# 实例
ssh -i ~/.ssh/id_rsa -L 8000:192.168.0.10:8000 wii@relay.company.com

# 多端口后台转发
ssh -i <secret> <user>@<host> -fCqTnN -L <port-local>:<ip>:<port-remote> -L <port-local>:<ip>:<port-remote> ...

-f -N: 仅后台转发端口
-C: 压缩数据d
-q: 安静模式
-T: 禁止远程分配终端
-n: 关闭标准输入
-N: 不执行远程命令

代理

1
2
# socks5 代理
ssh -D <localhost>:<local-port> <remote-host>

pem 文件登录

命令方式

1
ssh -i key.pem user@host

配置方式

1
2
3
4
Host <host>
User <user>
IdentityFile /path/to/key.pem
IdentitiesOnly yes

配置密码登录

1
2
3
4
5
6
sudo vim /etc/ssh/sshd_config
# 设置
PasswordAuthentication yes

# 重启 ssh 服务
sudo service sshd restart

远程执行命令

1
$ ssh -i /path/to/secret-key-file user@host "command"

示例

1
2
3
4
5
# 从 172.31.0.1 同步 consul 数据到本机
C="/usr/local/consul/consul kv export abtest-platform > /tmp/abtest-consul-data.json"
ssh mobdev@172.31.0.1 "$C"
scp mobdev@172.31.0.1:/tmp/abtest-consul-data.json /tmp/
/home/ubuntu/app/consul/consul kv import @/tmp/abtest-consul-data.json

免密登录

1
2
3
4
# 拷贝密钥, 免密登录
ssh-copy-id <user>@<host> -p <port>

# 手动拷贝 *.pub 内容添加至目标机 ~/.ssh/authorized_keys

无法免密登录

1
2
3
4
5
6
# 目标机
## 检查 authorized_keys 读写权限
chmod 0600 ~/.ssh/authorized_keys
## 检查 authorized_keys owner+group
chown <user> ~/.ssh/authorized_keys
chgrp <group> ~/.ssh/authorized_keys

网络

端口

查看进程监听的端口

1
2
# 查看进程在监听的端口
lsof -iTCP -sTCP:LISTEN | grep <pid/pname>

查看所有监听的端口

1
sudo netstat -tunlp

网络速度

  • iftop
  • nload
  • cbm
  • ifstat
1
2
3
4
sudo iftop

# 安装
sudo apt install iftop

nethogs

1
2
3
# 安装
sudo apt-get install nethogs
sudo yum install nethogs

使用

1
2
3
4
nethogs
nethogs eth1
nethogs [option] eth0 eth1
nethogs [option] eth0 eth1 ppp0

抓包

tcpdump

1
2
3
4
5
6
7
8
9
10
11
tcpdump -i <interface> port <port> 
tcpdump -i <interface> port <port> -w output.cap

# 其他用法
tcpdump -nS # 监听所有端口
tcpdump -nnvvS # 显示更详细的数据报文,包括 tos, ttl, checksum 等
tcpdump host <host> # 过滤主机
tcpdump src <host> # 过滤源主机
tcpdump dst <host> # 过滤目的主机
tcpdump net 0.0.0.0/24 # 过滤网络
tcpdump portrange <port-start>-<port-end> # 指定端口范围

输出日志说明

1
2
3
4
5
[S]: SYN(开始连接)
[.]: 没有 Flag
[P]: PSH(推送数据)
[F]: FIN (结束连接)
[R]: RST(重置连接)

自启动

1
2
3
crontab -e
# 添加如下内容
@reboot /path/to/program

查看进程网络链接

1
2
3
4
5
6
7
8
9
10
# 1. strace
strace -p $PID -f -e trace=network -s 10000

# 2. lsof
lsof -i -a -p $(pidof <process>)
## 持续观察
watch -n 1 lsof -i -a -p $(pidof <process>)

# 3. ss
ss -nap | grep $(pidof <process>)

查看系统信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# lsb_release
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.5 LTS
Release: 18.04
Codename: bionic

# os-release
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

# hostnamectl
$ hostnamectl
Static hostname: mvm
Icon name: computer-vm
Chassis: vm
Machine ID: 2d1d6a0bc90a451ab6ed062e9c2153bf
Boot ID: d8d4f12a272847b0b7d1de1ec2307493
Virtualization: qemu
Operating System: Ubuntu 18.04.5 LTS
Kernel: Linux 4.15.0-126-generic
Architecture: x86-64

# issue
$ cat /etc/issue
Ubuntu 18.04.5 LTS \n \l

查看发行版信息

1
2
3
# uname
$ uname -r # OR -a
4.15.0-126-generic

systemctl

查看日志

1
journalctl -u <service> -f

需求

同步文件夹

1
async -auz <path-to-local> user@host:/path/to/remote

Swap 分区

开启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 为 swap 分区创建空间
sudo fallocate -l 1G /swapfile
# 或使用 dd
sudo dd if=/dev/zero of=/swapfile bs=1024 count=1048576

# 2. 修改权限
sudo chmod 600 /swapfile

# 3. 创建 swap area
sudo mkswap /swapfile

# 4. 开启 swap
sudo swapon /swapfile

# 5. 显示状态
sudo swapon --show

# 6. 配置开机挂载
sudo vim /etc/fstab
## 输入如下内容
/swapfile swap swap defaults 0 0

关闭

1
2
3
4
5
6
# 1. 关闭 swap
sudo swapoff -v /swapfile

# 2. 移除 /etc/fstab 中的 swap 配置

# 3. 删除 /swapfile

alternatives

以 python 为例

1
2
3
4
5
6
7
8
9
10
# 更新
sudo update-alternatives --config python

# 添加选项
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.4 2
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 3

# 直接设置
sudo update-alternatives --set python /usr/bin/python3.6

core dump

1
2
3
4
5
6
# 生成 core 文件
ulimit -c unlimited # 临时
## 永久
vim /etc/security/limits.conf
# 添加内容
* soft core unlimited

列出 core dump 日志

1
$ coredumpctl list

core pattern

1
2
3
4
5
6
# core_pattern
# 查看 core_pattern
cat /proc/sys/kernel/core_pattern

# 默认
|/usr/lib/systemd/systemd-coredump %p %u %g %s %t %e"

路径

默认路径

1
/var/lib/systemd/coredump

修改路径

1
2
3
# 修改 core 文件路径
echo '/tmp/core_%e.%p' | sudo tee /proc/sys/kernel/core_pattern # 放到 /tmp 路径下
echo 'core_%e.%p' | sudo tee /proc/sys/kernel/core_pattern # 放到 working directory 下

节点间测速

1
2
3
4
5
6
7
8
# 安装 iperf
apt install iperf3

# node A
iperf3 -s

# node B
iperf3 -c <node-b>

dmesg

1
$ dmesg

错误信息原因参考这里

判断程序是否存在

1
2
3
4
command -v <program>

# 示例
command -v vim > /dev/null 2>&1 && echo "yes"