gh指令说明
1 | gh repo list kaylorchen |
MQTT服务器部署
使用emqx
1 | docker run --restart=always -d --name emqx -v ${PWD}/data:/opt/emqx/data -v ${PWD}/log:/opt/emqx/log -p 18083:18083 -p 1883:1883 emqx |
默认的账号密码是admin:public
传统mqtt服务器
下载mqttx客户端 https://mqttx.app/downloads 用于测试
使用docker启动服务1
2
3
4
5docker pull eclipse-mosquitto:2.0.20
docker run --name mqtt -d -p 1883:1883 eclipse-mosquitto:2.0.20
docker cp mqtt:/mosquitto $PWD/
docker stop mqtt
docker rm mqtt
修改配置文件 mosquitto/config/mosquitto.conf1
2
3
4
5
6listener 1883 0.0.0.0
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous false
password_file /mosquitto/config/pwfile
正式启动1
2
3touch mosquitto/config/pwfile
docker run --restart=always -d --name mqtt -p 1883:1883 -v ${PWD}/mosquitto:/mosquitto eclipse-mosquitto:2.0.20
docker exec -it mqtt mosquitto_passwd -c /mosquitto/config/pwfile kaylor
ZSH 配置和 FZF 配置
zsh 基本配置
1 | apt install zsh |
编辑~/.zshrc,修改一下on-my-zsh的默认插件和禁止其每次启动都启动更新, 请找到相应的行1
2zstyle ':omz:update' mode disabled
plugins=(git sudo extract z cp safe-paste colored-man-pages)
sudo插件是当你忘记加sudo的时候,连续按两次esc,就会在指令上添加sudo
extract是解压指令,无脑解压各种压缩包,再也不需要查询参数了
z是一个目录跳转指令,使用它替代cd的话,可以记录你的常用目录
cp的使用指令是cpv,是一个带进度条的拷贝指令
添加插件
在.zshrc 上添加如下内容:
1 | # zplug configruation |
私人化指令配置
有时候需要定制以下私人的指令,可以在 ~/.zshrc 文件中加入一行1
2
3[[ ! -f ~/.user.zsh ]] || source ~/.user.zsh
或
[[ ! -f ~/.user.bash ]] || source ~/.user.bash
然后创建并编辑 ~/.user.zsh 或者 ~/.user.bash, 输入你想要的指令1
2
3
4
5
6
7
8
9
10
11
12
13alias open='nautilus'
alias zsh_reload='source ~/.zshrc'
_systemctl_unit_state() {
typeset -gA _sys_unit_state
_sys_unit_state=( $(__systemctl list-unit-files "$PREFIX*" | awk '{print $1, $2}') ) }
function full_tar_with_sudo {
sudo tar -cvpzf $1 $2
}
function full_untar_with_sudo {
sudo tar -xvpzf $1 -C $2
}
安装配置 fzf
安装与升级
- Install
1 | git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf |
- Upgrade
1 | cd ~/.fzf && git pull && ./install |
基础使用
- 基础操作
1 | fzf # 输入fzf直接搜索 |
使用CTRL-J/CTRL-K(或者CTRL-N/CTRL-P)进行上下选择
使用Enter选中条目, CTRL-C/ESC进行退出操作
在多选择模式(-m), 使用TAB和Shift-TAB标记多个条目
Emacs 风格按键绑定
支持鼠标操作
- 语法匹配
标记 | 匹配类型 | 描述 |
---|---|---|
sbtrkt | 模糊匹配 | 内容匹配sbtrkt(字符匹配) |
‘wild | 精确匹配(单引号) | 内容包含单词wild(单词匹配) |
^music | 前缀精确匹配 | 以music开头 |
.mp3$ | 后缀精确匹配 | 以.mp3结尾 |
!fire | 反转匹配 | 内容不包含fire |
!^music | 前缀反转匹配 | 不以music开头 |
!.mp3$ | 后缀反转匹配 | 不以.mp3结尾 |
fzf的过滤默认是与操作,每个与操作之间使用空格间隔,如果需要使用或操作,参考下面的例子:1
^core go$ | rb$ | py$ # 表示以`core`开头, 且以`go`或`rb`或`py`结尾
- 一般快捷键和环境变量
按键 | 描述 |
---|---|
CTRL-T | 命令行打印选中内容 |
CTRL-R | 命令行历史记录搜索, 并打印输出 |
ALT-C | 模糊搜索目录, 并进入(cd),macos可以使用 cd **[TAB] |
name | description example |
---|---|
FZF_DEFAULT_COMMAND | 输入为 tty 时的默认命令 export FZF_DEFAULT_COMMAND=’fd –type f’ |
FZF_DEFAULT_OPTS | 设置默认选项 export FZF_DEFAULT_OPTS=”–layout=reverse –inline-info” |
FZF_CTRL_T_COMMAND | 按键映射行为设置 |
FZF_CTRL_T_OPTS | 按键映射选项设置 |
FZF_CTRL_R_OPTS | 按键映射选项设置 |
FZF_ALT_C_COMMAND | 按键映射行为设置 |
FZF_ALT_C_OPTS | 按键映射选项设置 |
个性化配置
更换搜索引擎(可选)
1
2brew install fd # Mac os
apt install fd-find # Ubuntu Linux设置环境FZF的环境变量
编辑 ~/.bashrc 或者 ~/.zshrc, 添加如下内容1
2
3export FZF_CTRL_T_COMMAND="fd --exclude={.git,.idea,.vscode,.sass-cache,node_modules,build} --type f --follow --hidden --color=always"
export FZF_DEFAULT_COMMAND="fd --exclude={.git,.idea,.vscode,.sass-cache,node_modules,build} --type f --follow --hidden --color=always"
export FZF_DEFAULT_OPTS="--height 60% --layout=reverse --preview '(highlight -O ansi {} || cat {}) 2> /dev/null | head -500' --ansi"
FZF_DEFAULT_COMMAND 依赖于安装了fd搜索指令,如果没有安装,可以不设置。
FZF_DEFAULT_OPTS 依赖于highlight指令,如果没有则会调用cat指令。Ubuntu可以通过apt install highlight安装该指令,MacOS可以通过brew install highlight安装该指令
- shell命令补全
fzf默认使用 ** + [TAB] 进行补全,常用的补全指令有:1
2
3
4
5kill -9 **
vim **
cd **
ssh **
export **
v4l2-ctl
获取支持的分辨率和编码格式
1 | v4l2-ctl --list-formats-ext -d /dev/video0 |
显示 Camera 所有信息(分辨率:Width/Height)
1 | v4l2-ctl -d /dev/video0 --all |
获取支持的编码格式
1 | v4l2-ctl --list-formats -d /dev/video0 |
获取支持的 camera 设备
1 | v4l2-ctl --list-devices -d /dev/video0 |
获取摄像头控制参数
1 | v4l2-ctl -d /dev/video0 --list-ctrls |
Samba 相关
挂载
vers 参数要指定
1 | sudo mount //192.168.100.1/share/ share/ -o vers=2.0 |
NFS 配置
安装 NFS
1 | sudo apt install nfs-kernel-server |
配置共享目录
服务端的共享目录配置文件为 /etc/exports
1 | # /etc/exports: the access control list for filesystems which may be exported |
1 | <输出目录> [客户端1 选项(访问权限,用户映射,其他)] [客户端2 选项(访问权限,用户映射,其他)] |
输出目录:
- 服务器共享的绝对目录地址
客户端:
- 指定 ip 地址的主机:192.168.0.200
- 指定子网中的所有主机:192.168.0.0/24 192.168.0.0/255.255.255.0
- 指定域名的主机:david.bsmart.cn
- 指定域中的所有主机:*.bsmart.cn
- 所有主机:*
选项:
- 访问权限
- 只读 ro
- 读写 rw
- 用户映射选项
- all_squash:将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody);
- no_all_squash:与 all_squash 取反(默认设置);
- root_squash:将 root 用户及所属组都映射为匿名用户或用户组(默认设置);
- no_root_squash:与 rootsquash 取反;
- anonuid=xxx:将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx);
- anongid=xxx:将远程访问的所有用户组都映射为匿名用户组账户,并指定该匿名用户组账户为本地用户组账户(GID=xxx);
- 访问权限
- 其他选项
- secure:限制客户端只能从小于 1024 的 tcp/ip 端口连接 nfs 服务器(默认设置);
- insecure:允许客户端从大于 1024 的 tcp/ip 端口连接服务器;
- sync:将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性;
- async:将数据先保存在内存缓冲区中,必要时才写入磁盘;
- wdelay:检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可以提高效率(默认设置);
- no_wdelay:若有写操作则立即执行,应与 sync 配合使用;
- subtree_check:若输出目录是一个子目录,则 nfs 服务器将检查其父目录的权限(默认设置);
- no_subtree_check:即使输出目录是一个子目录,nfs 服务器也不检查其父目录的权限,这样可以提高效率;
配置完成之后,重启 nfs service.
1 | sudo /etc/init.d/nfs-kernel-server restart |
客户端 mount
假设服务 IP 为: 192.168.20.200,
1 | kaylor@kaylor-ThinkPad-T460:~$ showmount -e 192.168.20.200 #显示服务器共享的目录 |
iptables 网络转发设置
设置内核转发
- 即时开启内核转发
1 | echo "1" > /proc/sys/net/ipv4/ip_forward |
- 永久开启内核转发
1 | vim /etc/sysctl.conf |
iptables 指令说明
PREROUTING(DNT)
这是 chain 的前端,是用来改变目标地址的
FORWARD
如果目标地址不是本机,机会进行转发。注意 linux 内核默认是禁止转发的,所以需要开启上面步骤的内核转发
POSTROUTING(SNAT)
它的作用是修改数据包的源地址,比如内网 IP 访问公网 IP,出口路由会将数据包的源地址改为自己的公网 IP,否者数据包有去无回。
链操作
操作参数
参数 | 描述 |
---|---|
-I | 插入 |
-A | 追加 |
-R | 替换 |
-D | 删除 |
-L | 列表显示 |
过滤参数
参数 | 描述 |
---|---|
-s | 匹配源地址 |
-d | 匹配目的地址 |
-p | 协议匹配 |
-i | 入接口匹配 |
-o | 出接口匹配 |
–sport,–dport | 源和目的端口匹配 |
-j | 跳转,也就是包的方向 |
! | 取反 |
- 列出 nat 表的所有规则
1 | iptables -t nat -n -L |
使用 -n 选项是因为避免长时间的反向 DNS 查询
- 添加一个规则到 filter 表的 FORWARD 链
1 | iptables -t filter -A FORWARD -s 10.1.1.11 -d 202.1.1.1 -j ACCEPT |
在 iptables 中,默认的表名就是 filter,所以这里可以省略-t filter 直接写成: iptables -A FORWARD -s 10.1.1.11 -d 202.1.1.1 -j ACCEPT
- 允许 eth3 接口过来的包通过 FORWARD 链
1 | iptables -A FORWARD -i eth3 -j ACCEPT |
简单 nat 路由器
- 环境介绍
linux 2.4 +
2 个网络接口
Lan 口:10.1.1.254/24 eth0
Wan 口:60.1.1.1/24 eth1
目的:实现内网中的节点(10.1.1.0/24)可控的访问 internet。
首先将 Lan 的节点 pc 的网关指向 10.1.1.254。
确定你的 linux 的 ip 配置无误,可以正确的 ping 通内外的地址。同时用 route 命令查看 linux 的本地路由表,确认指定了可用的 ISP 提供的默认网关。
操作
打开 linux 的转发功能:sysctl net.ipv4.ip_forward=1
将 FORWARD 链的策略设置为 DROP,这样做的目的是做到对内网 ip 的控制,你允许哪一个访问 internet 就可以增加一个规则,不在规则中的 ip 将无法访问 internet.
1 | iptables -P FORWARD DROP |
- 这条规则规定允许任何地址到任何地址的确认包和关联包通过。一定要加这一条,否则你只允许 lan IP 访问没有用
1 | iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT |
- 这条规则做了一个 SNAT,也就是源地址转换,将来自 10.1.1.0/24 的地址转换为 60.1.1.1
(因为是让内网上网,因此对于代理服务器而言 POSTROUTING(经过路由之后的包应该要把源地址改变为 60.1.1.1,否则包无法返回))
1 | iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -j SNAT --to 60.1.1.1 |
- 有这几条规则,一个简单的 nat 路由器就实现了。这时你可以将允许访问的 ip 添加至 FORWARD 链,他们就能访问 internet 了。
比如我想让 10.1.1.9 这个地址访问 internet,那么你就加如下的命令就可以了。
1 | iptables -A FORWARD -s 10.1.1.9 -j ACCEPT |
也可以精确控制他的访问地址,比如我就允许 10.1.1.99 访问 3.3.3.3 这个 ip
1 | iptables -A FORWARD -s 10.1.1.99 -d 3.3.3.3 -j ACCEPT |
或者只允许他们访问 80 端口
1 | iptables -A FORWARD -s 10.1.1.0/24 -p tcp --dport http -j ACCEPT |
端口转发
1 | iptables -t nat -A PREROUTING -d 10.8.1.24 -p tcp --dport 80 -j DNAT --to 192.168.111.111:80 |
借鉴此链接
保存 iptables 指令
- 使用 iptables-restore
设置了相关规则之后,保存到文件中
1 | iptables-save > /etc/iptables-rules |
然后新建一个脚本文件,保存到/etc/network/if-pre-up.d/目录下,记得修改脚本的权限:
1 |
|
- 使用 iptables-persistent
1 | sudo apt install iptables-persistent |
每当设置了新的 iptables 规则后,使用如下命令保存规则即可,规则会根据 ipv4 和 ipv6 分别保存在了/etc/iptables/rules.v4 和/etc/iptables/rules.v6 文件中。
1 | netfilter-persistent save |
日志相关
命令相关
显示全部最近一次重新引导后收集到的 journal 条目
1 | journalctl -b |
要查看上次引导的 journal 记录,则可使用-1 相对指针配合-b 标记
1 | journalctl -b -1 |
通过以下命令查看全部 2015 年 1 月 10 日下午 5:15 之后的条目
1 | journalctl --since "2015-01-10 17:15:00" |
过滤
1 | journalctl -u nginx.service |
显示内核信息
1 | journalctl -k |
根据优先级显示
0: emerg
1: alert
2: crit
3: err
4: warning
5: notice
6: info
7: debug
1 | journalctl -p err -b |
显示近期日志
1 | journalctl -n 20 |
追踪日志/实时滚动日志
1 | journalctl -f |
查看和删除系统日志
1 | journalctl --disk-usage |
查看 journald 进程信息
1 | sudo systemctl status systemd-journald.service |
更换系统log和开启log滚动
1 | sudo apt install syslog-ng |
编码中使用系统 log
安装依赖库
1 | apt install -y libsystemd-dev |
相关函数
1 | #include <systemd/sd-journal.h> |
The priority value is one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG, as defined in syslog.h
find 指令
指定目录搜索文件
1 | find dir -name "*pppoe*" |
Linux 内核编译指令
配置 config 文件
1 | make menuconfig |
根据已有的.config 文件,补充缺失的配置
1 | make defconfig |
编译内核和模块
1 | make |
单独编译模块和安装(不要轻易安装内核模块,如果不指定安装路径,容易损坏系统)
1 | make modules |
指定内核源码和模块源码所在的绝对路径
1 | make -C 内核源码绝对路径 M=模块源码文件所在的绝对路径 modules |
安装模块具体操作
1 | install -p -m 644 88XXau.ko /lib/modules/5.10.17-v7l+/kernel/drivers/net/wireless/ |
安装内核头文件
1 | make headers_install INSTALL_HDR_PATH=安装路径 |
nohup 指令
nohup 即不挂起,不会因为终端退出而终结
比如编译 Openwrt
1 | nohup make -j1 V=s >& make.log & 2>&1 |
客户定制 USB 设备号驱动加载
1 | sudo modprobe -r em28xx |
nload 分析网卡流量
1 | -a period Sets the length in seconds of the time window for average |
SSH
服务器端
编辑 /etc/ssh/sshd_config
1 | ClientAliveInterval 30 |
ClientAliveInterval 表示每隔多少秒,服务器端向客户端发送心跳,是的,你没看错。
下面的 ClientAliveInterval 表示上述多少次心跳无响应之后,会认为 Client 已经断开。
所以,总共允许无响应的时间是 60*3=180 秒。
客户端
编辑 /etc/ssh/ssh_config
1 | ServerAliveInterval 30 |
MacOS ssh转发
ssh的转发一般来说只要添加-A选项就可以了,但是macos默认没有把自己的秘钥添加,所以1
2ssh-add -l
ssh-add ~/.ssh/id_rsa
无法打开到身份验证代理的连接意味着您的计算机无法与身份验证代理程序通信。这通常发生在尝试使用SSH密钥进行身份验证时。要解决此问题,请执行以下步骤:
确保您的身份验证代理正在运行:
运行以下命令检查代理是否已启动:1
eval "$(ssh-agent -s)"
如果代理未运行,请运行以下命令启动代理:1
ssh-agent /bin/bash
添加您的SSH私钥:
运行以下命令将私钥添加到身份验证代理:1
ssh-add /path/to/your/private_key
如果您的私钥位于默认位置(如~/.ssh/id_rsa),则无需指定路径。
如果上述步骤不起作用,请尝试重新启动SSH服务:
sudo service ssh restart
如果问题仍然存在,请确保您的SSH私钥文件存在且您具有正确的访问权限。如果问题仍然无法解决,可能需要进一步调查您的操作系统和SSH配置。
X11应用转发
服务端安装X11服务和测试app1
apt install xorg x11-utils
客户端使用-X选项连接,并运行xclock测试1
2
3ssh [email protected] -X
xclock # 该指令运行在ssh的终端中
TMUX
在 home 目录下创建 .tmux.conf 文件
1 | setw -g mode-keys vi |
VIM
编辑 /etc/vim/vimrc
1 | set relativenumber |
GRUB
让 grub 记住你上一次的启动项
编辑 /etc/default/grub
1 | GRUB_DEFAULT=saved |
设置网卡名字为 eth*的形式
1 | GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0" |
执行指令更新 grub
1 | update-grub |
用户管理
- 添加一个组
1 | groupadd groupname |
- 添加一个新用户
1 | adduser new_user |
- 更改用户名
使用 root 用户登录
1 | killall -u old_username |
- 添加现有用户到一个组:
1 | usermod -a -G groupname username |
- 同时将 user 增加到 admins, ftp, www, 和 developers 用户组中,可以输入以下命令:
1 | useradd -G admins,ftp,www,developers user |
- 查看用户的 ID 信息
1 | id username |
文件传输
- rsync
拷贝文件不改变文件的权限和属性,记得使用sudo:1
2
3
4
5
6
7
8
9
10
11
12
13
14sudo rsync -avz /path/to/source/ /path/to/destination/ # 同步source文件夹下的所有文件
sudo rsync -avz /path/to/source /path/to/destination/ # 同步source文件夹
```
以下命令将从源目录拷贝所有文件和子目录到目标目录,但不拷贝符号链接:
```bash
rsync -av --no-links /path/to/source/ /path/to/destination/
```
如果您想要拷贝符号链接的目标文件,可以使用“-L”选项,如下所示:
```bash
rsync -avL /path/to/source/ /path/to/destination/
```
请注意,“-L”选项会将符号链接的目标文件拷贝到目标目录中,而不是链接本身。如果您想要拷贝链接本身,可以使用“-a”选项和“--copy-links”选项,如下所示:
```bash
rsync -a --copy-links /path/to/source/ /path/to/destination/
这将拷贝符号链接本身,而不是链接的目标文件。
网络抓包
基础
下面是一些用来配置 tcpdump 的选项,它们非常容易被遗忘,也容易和其它类型的过滤器比如Wireshark等混淆。
选项
- -i any 监听所有的网卡接口,用来查看是否有网络流量
- -i eth0 只监听eth0网卡接口
- -D 显示可用的接口列表
- -n 不要解析主机名
- -nn 不要解析主机名或者端口名
- -q 显示更少的输出(更加quiet)
- -t 输出可读的时间戳
- -tttt 输出最大程度可读的时间戳
- -X 以hex和ASCII两种形式显示包的内容
- -XX 与 -X类似,增加以太网header的显示
- -v, -vv, -vvv 显示更加多的包信息
- -c 只读取x个包,然后停止
- -s 指定每一个包捕获的长度,单位是byte,使用
-s0
可以捕获整个包的内容 - -S 输出绝对的序列号
- -e 获取以太网header
- -E 使用提供的秘钥解密IPSEC流量
表达式
在tcpdump中,可以使用表达式过滤指定类型的流量。有三种主要的表达式类型:type,dir,proto。
- 类型(type)选项包含:host,net,port
- 方向(dir)选项包含:src,dst
- 协议(proto)选项包含:tcp,udp,icmp,ah等
示例
捕获所有流量
查看所有网卡接口上发生了什么
tcpdump -i any
指定网卡接口
查看指定网卡上发生了什么
tcpdump -i eth0
原生输出
查看更多的信息,不解析主机名和端口号,显示绝对序列号,可读的时间戳
tcpdump -ttttnnvvS
查看指定IP的流量
这是最常见的方式,这里只查看来自或者发送到IP地址1.2.3.4的流量。
tcpdump host 1.2.3.4
查看更多的包信息,输出HEX
当你需要查看包中的内容时,使用hex格式输出是非常有用的。
# tcpdump -nnvXSs 0 -c1 icmp
tcpdump: data link type PKTAP
tcpdump: listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
16:08:16.791604 IP (tos 0x0, ttl 64, id 34318, offset 0, flags [none], proto ICMP (1), length 56)
192.168.102.35 > 114.114.114.114: ICMP 192.168.102.35 udp port 50694 unreachable, length 36
IP (tos 0x0, ttl 152, id 0, offset 0, flags [none], proto UDP (17), length 112)
114.114.114.114.53 > 192.168.102.35.50694: [|domain]
0x0000: 5869 6c88 7f64 784f 4392 ed7e 0800 4500 Xil..dxOC..~..E.
0x0010: 0038 860e 0000 4001 e906 c0a8 6623 7272 [email protected]#rr
0x0020: 7272 0303 3665 0000 0000 4500 0070 0000 rr..6e....E..p..
0x0030: 0000 9811 16cd 7272 7272 c0a8 6623 0035 ......rrrr..f#.5
0x0040: c606 005c 0000 ...\..
1 packet captured
357 packets received by filter
0 packets dropped by kernel
使用源和目的地址过滤
tcpdump src 2.3.4.6
tcpdump dst 3.4.5.6
过滤某个子网的数据包
tcpdump net 1.2.3.0/24
过滤指定端口相关的流量
tcpdump port 3389
tcpdump src port 1025
过滤指定协议的流量
tcpdump icmp
只显示IPV6流量
tcpdump ip6
使用端口范围过滤
tcpdump portrange 21-23
基于包的大小过滤流量
tcpdump less 32
tcpdump greater 64
tcpdump <=128
将捕获的内容写入文件
使用-w
选项可以将捕获的数据包信息写入文件以供以后分析,这些文件就是著名的PCAP(PEE-cap)文件,很多应用都可以处理它。
tcpdump port 80 -w capture_file
使用tcpdump加载之前保存的文件进行分析
tcpdump -r capture_file
高级
使用组合语句可以完成更多高级的过滤。
- AND: and or &&
- OR: or or ||
- EXCEPT: not or !
过滤指定源IP和目的端口
tcpdump -nnvvS src 10.5.2.3 and dst port 3389
过滤指定网络到另一个网络
比如下面这个,查看来自192.168.x.x的,并且目的为10.x或者172.16.x.x的所有流量,这里使用了hex输出,同时不解析主机名
tcpdump -nvX src net 192.168.0.0/16 and dst net 10.0.0.0/8 or 172.16.0.0/16
过滤到指定IP的非ICMP报文
tcpdump dst 192.168.0.2 and src net and not icmp
过滤来自非指定端口的指定主机的流量
下面这个过滤出所有来自某个主机的非ssh流量
tcpdump -vv src mars and not dst port 22
复杂分组和特殊字符
当构建复杂的过滤规则的时候,使用单引号将规则放到一起是个很好的选择。特别是在包含()的规则中。比如下面的规则就是错误的,因为括号在shell中会被错误的解析,可以对括号使用\
进行转义或者使用单引号
tcpdump src 10.0.2.3 and (dst port 3389 or 22)
应该修改为
tcpdump 'src 10.0.2.3 and (dst port 3389 or 22)'
隔离指定的TCP标识
可以基于指定的TCP标识(flag)来过滤流量。
下面的过滤规则中,tcp[13] 表示在TCP header中的偏移位置13开始,后面的数字代表了匹配的byte数。
显示所有的URGENT (URG)包
tcpdump 'tcp[13] & 32!=0'
显示所有的ACKNOWLEDGE (ACK)包
tcpdump 'tcp[13] & 16!=0'
显示所有的PUSH(PSH)包
tcpdump 'tcp[13] & 8!=0'
显示所有的RESET(RST)包
tcpdump 'tcp[13] & 4!=0'
显示所有的SYNCHRONIZE (SYN) 包
tcpdump 'tcp[13] & 2!=0'
显示所有的FINISH(FIN)包
tcpdump 'tcp[13] & 1!=0'
显示说有的SYNCHRONIZE/ACKNOWLEDGE (SYNACK)包
tcpdump 'tcp[13]=18'
其它方式
与大多数工具一样,也可以使用下面这种方式来捕获指定TCP标识的流量
tcpdump 'tcp[tcpflags] == tcp-syn'
tcpdump 'tcp[tcpflags] == tcp-rst'
tcpdump 'tcp[tcpflags] == tcp-fin'
识别重要流量
最后,这里有一些重要的代码片段你可能需要,它们用于过滤指定的流量,例如畸形的或者恶意的流量。
过滤同时设置SYN和RST标识的包(这在正常情况下不应该发生)
tcpdump 'tcp[13] = 6'
过滤明文的HTTP GET请求
tcpdump 'tcp[32:4] = 0x47455420'
通过横幅文本过滤任意端口的SSH连接
tcpdump 'tcp[(tcp[12]>>2):4] = 0x5353482D'
过滤TTL小于10的包(通常情况下是存在问题或者在使用traceroute)
tcpdump 'ip[8] < 10'
过滤恶意的包
tcpdump 'ip[6] & 128 != 0'
GIT
- 变基
1 | git checkout experiment |
- 一般的合并
把 dev 合并到 master
1 | git checkout master |
- 分支重命名
本地分支重命名1
git branch -m new_name
远程分支重命名为本地分支名1
git branch -m <旧分支名> <新分支名>
- 解绑上游分支
1 | git branch --unset-upstream |
- clone 指定分支
1 | git clone -b dev_branch [url] |
–depth=1 参数,克隆最近一次的 commit 的,体积会变小
1 | git clone https://github.com/xxx/xxx.git --depth=1 |
如果需要间该分支所有的 commit 克隆下来,需要
1 | git fetch --unshallow |
但会产生另外一个问题,他只会把默认分支 clone 下来,其他远程分支并不在本地,所以这种情况下,需要用如下方法拉取其他分支:
1 | git remote show origin |
- git bash 显示中文
1 | git config --global core.quotepath false |
- 取消文件跟踪
1 | git rm -r --cached dir #不跟踪,但保留文件 |
- 远程仓库(remote)
1 | git remote add origin [url] |
- 推送分支
1 | git push --set-upstream origin master |
- 拉取远程分支
1 | git pull <远程库名> <远程分支名>:<本地分支名> |
- 查看分支,并 checkout
1 | git branch –av |
- 删除本地分支
删除 merge 了的分支
1 | git branch -d xxx |
删除分支(不管它有没有 merge)
1 | git branch -D xxx |
删除远程分支
1 | git push origin --delete branch_name |
远程分支已经删除,删除本地的origin/branch引用1
git branch -d -r origin/branch
远程分支和本地代码都删除1
git branch -D -r origin/branch
- 补丁
1 | git format-patch xxxxxxxxxx |
- 修改 commit 的 message
1 | git commit --amend -m "I miss you" |
- 代理
加代理
1 | git config --global http.proxy 'socks5://127.0.0.1:1080' |
取消代理
1 | git config --global --unset http.https://github.com.proxy |
- Linux 配置文件
编辑全局配置文件 ~/.gitconfig
1 | [user] |
- tag 使用
1 | git tag v1.0.0 |
ROS 常用指令
- 配置 ROS 环境变量(临时)
1 | export ROS_IP=192.168.15.147 |
- 设置 ROS Log 等级
1 | rqt_logger_level |
Ubuntu 启动分析
1 | systemd-analyze plot > boot.svg |
分区自动挂载和格式化
格式化分区的时候使用 -E root_owner=1000:1000 选项1
sudo mkfs.ext4 -E root_owner=1000:1000 /dev/sda1
确认系统有autofs4内核模块的支持,如果没有将不能使用x-systemd.automount选项,编辑/etc/fstab,添加1
/dev/sda1 /opt/storage ext4 nofail,user,exec,rw,x-systemd.automount 0 0
x-systemd.automount选项是使用是挂载,没有使用的时候不挂载。
网络配置
netplan 网络配置
编辑 /etc/netplan/50-cloud-init.yaml
1 | # This file is generated from information provided by |
IP 指令
- ipv4:
1 | ip -4 addr |
- ipv6:
1 | ip -6 addr |
- 基本网卡操作:
1 | ip addr show eth0 |
- 添加和删除路由和默认网关
1 | ip route add default via 192.168.1.254 |
- 特殊路由
路由查找遵循“最长匹配原则”,当路由器收到一个IP数据包时,会将数据包的目的IP地址与自己本地路由表中的表项进行bit by bit的逐位查找,直到找到匹配度最长的条目,这叫最长匹配原则。
最简单的理解方式就是,当路由都匹配的时候,看看谁的子网掩码位数比较多。
1 | ip route add 0.0.0.0/1 via 192.168.23.1 dev eth0 |
静态 IP 和 DNS 设置
- 设置静态 IP
1 | hunter@hunter-Drone:~$ cat /etc/network/interfaces |
为了支持 DNS,需要安装 apt install resolvconf ifupdown
如果为了保证有一个固定的 DNS,可以编辑 /etc/resolvconf/resolv.conf.d/tail, 添加一个默认 DNS
1 | nameserver 114.114.114.114 |
桥接多网口
安装桥接工具 sudo apt install bridge-utils , 生成网桥配置文件 /etc/network/interfaces.d/br0 ,你会看到如下内容:
1 | auto br0 |
- interfaces的一些特殊配置
pre-up | 网卡启动前的动作 |
up | 启动时的动作 |
post-up | 启动后的动作 |
down | 关闭时的动作 |
pre-down | 关闭前的动作 |
post-down | 关闭后的动作 |
比如我们在网卡启动之后添加特殊的路由表1
2
3
4
5
6auto eth0
iface eth0 inet static
address 192.168.23.10
netmask 255.255.255.0
post-up ip route add 128.0.0.0/1 via 192.168.23.1
post-up ip route add 0.0.0.0/1 via 192.168.23.1
- CAN 接口配置
1 | edge@host-63b5d7:/etc/network/interfaces.d$ cat can0 |
无线网络配置
1 | kaylor@kaylor-ThinkPad-T460:~$ wpa_passphrase ssid password |
使用以上指令生成配置文件,然后在 /etc/network/interfaces.d/ 下建立 wlan0 文件,内容如下:
1 | allow-hotplug wlan0 |
如果不使用指定的配置文件,也可以如下:
1 | auto wlan0 |
网络启动等待的问题
有时候设置了接口的DHCP服务,网络会一直在等待,最后只有网络服务启动超时了,才能启动系统。可以通过修改启动超时参数达到目的。
1 | ╰─ cat /lib/systemd/system/networking.service |
为再缩短启动时间,我们可以设置系统的systemd的默认启动超时时间,编辑 /etc/systemd/system.conf, 添加以下内容:1
2DefaultTimeoutStartSec=10s
DefaultTimeoutStopSec=10s
NetworkManager 管理相关
永久不管理接口
- 查看网卡状态
1 | nmcli device status |
- 编辑文件 /etc/NetworkManager/conf.d/99-unmanaged-devices.conf
NetworkManager 的系统配置文件可能的位置还有 /lib/NetworkManager/conf.d/ 和 /usr/lib/NetworkManager/conf.d/
1 | [keyfile] |
- 重启服务
1 | systemctl reload NetworkManager |
临时更改接口管理状态
1 | nmcli device set enp1s0 managed no/yes |
NAT 转发设置
使用主机作为网关给其他设备上网
1 | echo "Forward setting" |
iw 指令 (无线网络)
1 | iw help # 帮助 |
Python 的简易 httpserver
1 | python -m SimpleHTTPServer 8080 |
Udev 检查指令
查看某个设备的详细信息,如/dev/video0
1 | udevadm info -a /dev/video0 |
编辑匹配规则(/etc/udev/rules.d/10-local.rules):
规则中只能包含单个父设备
1 | #map cameras to clear names |
重命名网卡
1 | KERNEL=="wlan*", SUBSYSTEMS=="sdio", NAME="hostapd" |
触发规则
1 | sudo udevadm trigger |
查看文件夹大小
1 | du |
dd 指令
- 生成空的 image 和扩容
1 | dd if=/dev/zero of=disk.img bs=1M count=256 #生成256MBytes的image |
追加之后的扩容操作,需要参考接下来的“使用 parted 扩容分区”,对 image 进行分区,请参考我的另一个文章制作一个空的 image
- 烧写 image
1 | gunzip -c kaylor.img.gz | dd of=/dev/xxx bs=20M |
使用 parted 扩容分区
- 修改分区表
1 | sudo parted /dev/sdb |
打印信息如下:
1 | GNU Parted 3.2 |
上述的指令可以复合成:
1 | sudo parted -s /dev/sdb resizepart 1 15.8G |
- 恢复文件系统
1 | sudo e2fsck -f /dev/sdb1 |
- 扩容
1 | sudo resize2fs /dev/sdb1 |
APT
- 列出软件包可用版本
1 | apt-cache madison package-name |
- 查看当前apt配置
1 | apt-config dump |
这个指令可以过滤Install,设置一下apt默认的安装设置,比如
1
2
3 ❯ cat /etc/apt/apt.conf.d/99user
APT::Install-Recommends "0";
APT::Install-Suggests "0";
- 查看某个软件包的可用版本
1 | apt policy syslog-ng |
1 | Package: * |
- 重新安装某个包的时候,询问是否覆盖配置文件
1
apt reinstall package -o Dpkg::Options::="--force-confask"
GDB设置
设置ulimited
临时设置
1
2
3
4
5❯ ulimit -c
0
❯ ulimit -c unlimited
❯ ulimit -c
unlimited永久设置
编辑/etc/security/limits.conf文件,在文件末尾添加1
2* soft core unlimited
* hard core unlimited
- 设置coredump文件格式和位置
在/etc/sysctl.conf中添加1
2kernel.core_pattern = ./core_%e_%t_%p
kernel.core_uses_pid = 0
docker
基本指令
1 | docker ps -l #查看上一次运行的容器 |
守护式容器
1 | docker run -i -t ubuntu /bin/bash #启动之后使用Ctrl+P 和 Ctrl+Q |
容器端口映射
1 | dodker run -P -i -t ubuntu /bin/bash #-P --publish-all=true|false default: false |
跨平台使用 docker
运行特权容器
1 | docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d |
查看支持的 CPU 信息
1 | ls -al /proc/sys/fs/binfmt_misc/ |
主机文件夹映射
1 | docker run -it -v /home/kaylor/wifibroadcast/:/data --name rpi_env kaylor/rpi-env:20210507 /bin/bash |
镜像
1 | docker images [options] [repository] |
查找 Images
- 从网站查找
https://registry.hub.docker.com - 使用命令
1 | docker search [options] term #最多返回25个结果 |
拉取 Images
1 | docker pull [options] NAME[:TAG] |
推送镜像
1 | docker push repository |
配置国内镜像地址
编辑 /etc/docker/daemon.json
1 | { |
构建镜像
1 | docker commit #通过容器构建 |
Doker 的 C/S 模式
- Romote API
unix:///var/run/docker.sock
tcp://host:port
fd://socketfd
Docker 的守护进程
docker -d [options]
-D, –debug=false
-e, –exec-driver=”native”
-g, –graph=”var/lib/docker”
–icc=true
-l, –log-level=”info”
–lable=[]
-p, –pidfile=””/var/run/docker.pid
-G, –group=”docker”
-H, –host=[]
–tls=false
–tlscacert=”/home/kaylor/.docker/ca.pem”
–tlscert=”/home/kaylor/.docker/cert.pem”
–tlskey=”/home/kaylor/.docker/key.pem”
–tlsverify=false
Registry 相关:
–insecure-registry=[]
–registry-mirror=[]
网络相关:
-b, –bridge=””
–bip=””
–fixed-cidr=””
–fixed-cidr-v6=””
–dns=[]
–dns-search=[]
–ip=0.0.0.0
–ip-forward=true
–ip-masq=true
–iptables=true
–ipv6=false
–mtu=0
Docker 环境变量
export DOCKER_HOST=”tcp://x.x.x.x:2375”
镜像保存与加载
1 | docker save -o 要保存的文件名 要保存的镜像 |
dockerfile 指令
Dockerfile 例子
1 | FROM ubuntu:14.04 |
- FROM
1 | FROM <image> |
必须是 dockerfile 的第一条指令
- MAINTAINER
1 | MAINTAINER <name> |
包含作者和联系信息
- RUN
1 | RUN <command> |
1 | RUN ["executalbe", "param1", "param2"] |
- EXPOSE
1 | EXPOSE <port> [<port>...] |
虽然我们在镜像构建中指定了暴露的端口号,但在容器运行时,我们仍需要手动的指定容器的端口映射,就像我们之前曾经使用的这个 docker run 命令。也就是说,在 dockerfile 中使用 expose 指令来指定的端口,只是告诉 Docker,该容器内的应用程序会使用特定的端口儿,但是出于安全的考虑,Docker 并不会自动地打开端口,是需要在使用时再 run 命令中添加对端口的映射指令。
- CMD
1 | CMD ["executalbe", "param1", "param2"] |
cmd 是指定容器运行时的默认指令,如果 docker run 带指令,会覆盖 cmd 的指令
- ENTRYPOINT
1 | ENTRYPOINT ["executalbe", "param1", "param2"] |
docker run 的指令不能覆盖该指令。
- ADD and COPY
1 | ADD/COPY src dest |
add 包含 tar 的解压缩功能,复制推荐使用 copy
- VOLUME
- WORKDIR
- ENV
- USER
- ONBUILD
fswebcam 命令行拍照
1 | fswebcam -S 10 -r 640x480 --no-banner 1.jpg |
PVE 指令
1 | qm stop ID #关机 |
exec, source 和 fork 的区别
fork (/directory/script.sh) :如果 shell 中包含执行命令,那么子命令并不影响父级的命令,在子命令执行完后再执行父级命令。子级的环境变量不会影响到父级。
fork 是最普通的, 就是直接在脚本里面用 /directory/script.sh 来调用 script.sh 这个脚本. 运行的时候开一个 sub-shell 执行调用的脚本, sub-shell 执行的时候, parent-shell 还在。sub-shell 执行完毕后返回 parent-shell 。 sub-shell 从 parent-shell 继承环境变量.但是 sub-shell 中的环境变量不会带回 parent-shell 。整个执行的过程是 fork + exec + waitpid (此三者均为系统调用)。
exec (exec /directory/script.sh) :执行子级的命令后,不再执行父级命令。
exec 与 fork 不同,不需要新开一个 sub-shell 来执行被调用的脚本. 被调用的脚本与父脚本在同一个 shell 内执行。但是使用 exec 调用一个新脚本以后, 父脚本中 exec 行之后的内容就不会再执行了。这是 exec 和 source 的区别。
source (source /directory/script.sh) :执行子级命令后继续执行父级命令,同时子级设置的环境变量会影响到父级的环境变量。