linux常用命令


系統相關:

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        # server版沒有安裝這個。
問題: 
    卸載完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        # 安裝server版一開始的default 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 --purge xxx 

查看系統信息:

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)與重定向:

每個命令執行都會產生三個文件描述符012
    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://www.codebelief.com
2. 顯示 HTTP 頭 
    curl -I http://127.0.0.1:8500   只想要顯示 HTTP 頭,而不顯示文件內容
    curl -i http://127.0.0.1:8500   同時顯示 HTTP 頭和文件內容
3. 將鏈接保存到文件 
    方法一  curl http://www.codebelief.com > index.html    
    方法二  curl -o index.html http://www.codebelief.com   結果會被保存到命令行中提供的文件名 
    方法三  curl -O http://www.codebelief.com/page/2/      URL 中的文件名會被用作保存輸出的文件名,必須確保鏈接末尾包含文件名
4. 同時下載多個文件
    curl -o page1.html http://www.codebelief.com/page/1/ -o page2.html http://www.codebelief.com/page/2/
    curl -O http://www.codebelief.com/page/2/ -O http://www.codebelief.com/page/3/
5. 使用 -L 跟隨鏈接重定向 
    curl -L http://codebelief.com   正常情況下無法自動跳轉
6. 使用 -A 自定義 User-Agent
    curl -A “Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0” http://www.baidu.com
7. 使用 -H 自定義 header 
    curl -H “Referer: www.example.com” -H “User-Agent: Custom-User-Agent” http://www.baidu.com 
    curl -H “Cookie: JSESSIONID=D0112A5063D938586B659EF8F939BE24” http://www.example.com 
8. 使用 -c 保存 Cookie 
    curl -c “cookie-example” http://www.example.com
9. 使用 -b 讀取 Cookie 
    -H也可
    curl -b “JSESSIONID=D0112A5063D938586B659EF8F939BE24” http://www.example.com
    如果要從文件中讀取 Cookie,-H 就無能為力了,此時可以使用 -b 來達到這一目的: 
    curl -b “cookie-example” http://www.example.com
10. 使用 -d 發送 POST 請求
    -d 用於指定發送的數據,-X 用於指定發送數據的方式
    POST請求
        curl -d “userName=tom&passwd=123456” -X POST http://www.example.com/login
    在使用 -d 的情況下,如果省略 -X,則默認為 POST 方式: 
        curl -d “userName=tom&passwd=123456” http://www.example.com/login
    GET請求
        curl -d “somedata” -X GET http://www.example.com/api
        或者使用 -G 選項: 
        curl -d “somedata” -G http://www.example.com/api
    從文件中讀取 data 
        curl -d “@data.txt” http://www.example.com/login

取得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   # 所有非空寫入文件bak中
    tar -cvf conf.tar /etc/* 
    tar -tvf conf.tar|grep yum.repos.d      # 壓縮所有文件並查找其中包含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內出現,加上--no-check-certificate后解決,測試ubuntu:18.04.5鏡像沒有該問題
原因: 
    發現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 --ca-certificate=/etc/ssl/certs/ca-certificates.crt
其他方案:
    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{} //{command1; command2} END{}’ file
        [-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
                # group passwd可以使得其他用戶可以通過newgrp命令來接觸到該文件
                # group list有必要包含用戶額外隸屬的群組,/etc/passwd預設群組不必要包含

用戶管理:

useradd[參數][用戶名]        # sudo adduser 用戶名
區別:
    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  查看目錄下文件
    文件的類型
    文檔所有者的權限
    與所有者同在一個組的用戶的權限情況
    其他用戶的權限情況
    文件硬鏈接數 # 文件為1,目錄一般來說至少為2,因為包含了. and ..,但是不是所有的文件系統都使用. and ..
    文件(目錄)擁有者   
    文件(目錄)擁有者所在的組   
    文件所占用的空間(以字節為單位)
    文件(目錄)最近訪問(修改)時間
    文件(目錄)名
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 --purge remove     刪除已安裝包(不保留配置文件)。
sudo apt-get update #更新apt軟件源數據庫
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://ports.ubuntu.com/ xenial main restricted
deb [arch=arm64] http://ports.ubuntu.com/ xenial-updates main restricted
deb [arch=arm64] http://ports.ubuntu.com/ xenial universe
deb [arch=arm64] http://ports.ubuntu.com/ xenial-updates universe
deb [arch=arm64] http://ports.ubuntu.com/ xenial multiverse
deb [arch=arm64] http://ports.ubuntu.com/ xenial-updates multiverse
deb [arch=arm64] http://ports.ubuntu.com/ xenial-backports main restricted universe multiverse

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 --prefix=/usr/local/python3
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 --no-check-certificate  https://pypi.python.org/packages/source/s/setuptools/setuptools-19.6.tar.gz#md5=c607dd118eae682c44ed146367a17e26
    tar -zxvf setuptools-19.6.tar.gz
    cd setuptools-19.6
    python3 setup.py build
    python3 setup.py install

    wget --no-check-certificate  https://pypi.python.org/packages/source/p/pip/pip-8.0.2.tar.gz#md5=3a73c4188f8dbad6a1e6f6d44d117eeb
    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 --output 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";          # 是否鎖住apt
編輯/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允許
#!/bin/bash  指定什么解析器    #開頭是shell的注釋
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     #[ 表達式 ]等同於test命令,if [ 1 == 1 ];then echo 1;fi
if command;then     ;fi     #

-eq 測試兩個整數是否相等
-ne 測試兩個整數是否不等
-gt 測試一個數是否大於另一個數
-lt 測試一個數是否小於另一個數
-ge 大於或等於
-le 小於或等於

字符串測試(兩邊要有空格)
    == 等於  
    != 不等
    >  大於
    <  小於
    -z string 測試指定字符是否為空,空着真,非空為假
    -n string 測試指定字符串是否為不空,空為假 非空為真     #if [ -n sss ];then echo 1;fi

    文件測試
    -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        # :表示永遠為true
until [];do command;done

輸入:

read 變量名:輸入字符串並賦值給該變量    -p  提示信息
例子:while read -p "please input a name" name; do echo $name $RANDOMdone

函數:

function name ()
{

}
可以加return返回值,也可以不帶,如果不帶就以最后一條命令運行結果,作為返回值。
# 帶function關鍵字,也可以不帶

數組操作:

定義:

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

# 注意的是 unit.sh腳本 不能通過sh xxx.sh的方式執行,不然獲取不到$1.

文件傳輸:

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    # 查找當前用戶占用端口的進程(List Open Files)
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 & # 可以在你退出帳戶之后繼續運行相應的進程。nohup就是不掛起的意思( no hang up)

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 1done

查看進程的具體信息:

資源占用:

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         # 系統默認的bash shell的第一啟動文件,系統中所有用戶登錄時都會執行這個啟動文件
加入:
    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 # 可能當前用戶需要文件夾的權限
    # /usr/local/python3/bin/echo_supervisord_conf > /etc/supervisord.conf  在python3中
    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

    # stdout_logfile如果不包含print輸出,python -u /xxx即可。  
操作:
    啟動:
        supervisord -c  /etc/supervisord.conf   # 確保都該注釋的注釋掉了(不要sudo啟動)有時會報spawn error,通過下面的形式啟動
        或/usr/bin/python /usr/local/bin/supervisord # 報error就設置對應目錄的權限  python3要創建軟鏈
        # unlink /tmp/supervisor.sock
    重啟supervisord主進程:
        supervisorctl reload                載入最新的配置文件,停止原有進程並按新的配置啟動、管理所有進程。
    關閉supervisord:
        supervisorctl shutdown
    查看:
        supervisorctl status
    啟動或者停止服務:
        supervisorctl stop|start|restart program_name       # 適合修改py文件后重新啟動
    重讀所有配置文件:
        supervisorctl reread 
    重讀后更新program配置:
        supervisorctl update program名字                  # 適合僅配置修改,不用重啟py進程,新添加任務也通過這個來add啟動
        supervisorctl update                                # 不加名字時全部更新,自動移除舊棄的任務
    添加/移除任務
        supervisorctl remove/add xxx
分組:
    [group:model]
    programs=dch,sms            # 填寫各個配置文件下的項目name,可以不同文件,然后reread后update即可統一管理
PYTHONPATH環境變量設置:
    [supervisord]
    environment=PYTHONPATH='/home/ubuntu/data/code/feature-data-service'    為所有的program添加環境變量
    # 默認會啟動的腳本會獲取到supervisor啟動以來設置的環境變量,shutdown然后重新啟動即可獲取最新的(reload沒用)
    # environment只是用來單獨設置用的
瀏覽器訪問:
    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這種

            # 執行的命令必須是立刻返回或者后台運行的,不然下面的命令會執行不了(具體想看/etc/rc.local執行了哪些命令+,可以設置log)
                python xxx.py 改為 nohup python xxx.py &

        設置日志輸出:
            /etc/rc.local文件開頭加入:
                exec 2> /tmp/rc.local.log           # 成功執行會被標記為 + /usr/bin/supervisord
                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         # nginx要sudo才行
            sudo /bin/su - ubuntu -c "/usr/bin/supervisord"   # 其他如supervisord切換用戶啟動
        sudo chmod 755 /etc/init.d/test
        sudo update-rc.d /etc/init.d/test defaults 95           # 將該腳本放到啟動列表,其中數字95是腳本啟動的順序號
        sudo update-rc.d -f test remove     # 移除 
        service test status             # 查看status,如果是普通shell命令會直接執行
        centos系統下
            腳本開頭需要添加注釋:
                # chkconfig: - 85 15
                # description: nginx is a World Wide Web server. It is used to serve
            執行命令
                sudo chkconfig --add nginx
                sudo chkconfig --del nginx
        # 復雜命令能夠server xxx stop和server xxx start,網上搜索即可
            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           # 注意init.d里的腳本PATH有這個路徑才行
環境問題:
    不啟動任何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           # size  
        missingok       # 在日志輪循期間,任何錯誤將被忽略,例如“文件無法找到”之類的錯誤。
        rotate 30       # 保留多少個日志文件(輪轉幾次)
        compress        # 通過gzip壓縮轉儲以后的日志,通過 gzip -dv xx.log.gz解壓
        dateext         # 切割后的日志文件以當前日期為格式結尾,如xxx.log-20131216這樣,如果注釋掉,切割出來是按數字遞增,即xxx.log-1這種格式
        delaycompress   # 和compress 一起使用時,轉儲的日志文件到下一次轉儲時才壓縮
        notifempty      # 當日志文件為空時,不進行輪轉
        sharedscripts   
        prerotate       # 在logrotate轉儲之前需要執行的指令,例如修改文件的屬性等動作;必須獨立成行
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate      # 運行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"      # 公鑰私鑰在~/.ssh目錄下,每次生成會覆蓋舊的密鑰對,指定的賬號在gitlab有用,用來尋找對應的ssh公鑰
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys         # 文件權限為600,用途:存放認證公鑰,ssh登錄驗證的公鑰只要在里面有就可以了
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.gztgz只是兩種不同的書寫方式,后者是一種簡化書寫,等同處理
這種格式是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, --gzip filter the archive through gzip 通過gzip壓縮的形式對文件進行歸檔
配套tar與bzip2
tar cvf tarfile.tar.gz --use-compress-program=bzip2 files 
tar cvf tarfile.tar.gz --use=bzip2 files 

解壓:

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為不備份,置12為備份,但2的備份重要性比1
            第6列設置是否開機的時候使用fsck檢驗所掛載的磁盤,置0為不檢驗,置12為檢驗,但置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

2. vim /etc/fstab Commenting out the swap partition's UUID in the following file:

sed -i 'd/swap/d' /etc/fstab

3. /etc/initramfs-tools/conf.d/resume

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://github.com/dokan-dev/dokany/releases/download/v1.0.0/DokanSetup_redist-1.0.0.5000.exe
https://github.com/feo-cz/win-sshfs/releases
安裝這兩個即可

查找:

查找文件夾中內容包含關鍵字的文件:

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 --rm ikubernetes/stress-ng  /usr/bin/stress-ng --cpu 2 --cpu-load 100 --metrics-brief
/usr/bin/stress-ng --cpu 2 --cpu-load 100 --metrics-brief
起一個進程對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 --vm 1 --vm-bytes 85% --vm-keep
/usr/bin/stress-ng --cpu 7 --cpu-load 100 --vm 1 --vm-bytes 85% --vm-keep
使用率:
    (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 --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/
~/.pip/pip.conf(window下%HOMEPATH%\pip\pip.ini)        # pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
                                                        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 --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
conda config --show-sources

docker:

/etc/docker/daemon.json
    "registry-mirrors":["https://expuzg6d.mirror.aliyuncs.com"]
systemctl restart docker

window
    https://cr.console.aliyun.com/
    https://expuzg6d.mirror.aliyuncs.com
    右鍵應用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 --purge *nvidia-\*
apt -y autoremove
rm /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 (可以手動link)
dpkg -l | grep -i nvidia
dpkg --purge xxx    # 不一定清理干凈,執行上面三步和下面的rmmod即可
關於/proc/driver/nvidia/version仍然顯示
    cat /proc/driver/nvidia/version
    lsmod | grep nvidia
    rmmod nvidia   # 先移除依賴服務,如果提示in use需要kill進程或者重啟

    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 --list | grep nvidia-*
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 --runtime=nvidia --rm nvidia/cuda nvidia-smi   # 值得注意的是,配置default runtime后,docker run啟動的容器能看到所有的卡,除非啟動時-e NVIDIA_VISIBLE_DEVICES=none
    深究原因:
        這是因為鏡像編譯的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,會獲取所有卡   # 能看到所有卡的情況1
            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,默認掛載所有卡                 # 能看到所有卡的情況2
    重大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 --rm --gpus all

容器內是否需要安裝驅動:

目前看來只需要安裝cuda即可,driver相關通過nvidia-docker這個runtime來處理,鏡像不需要安裝。

問題:

1. Failed to initialize NVML: Unknown Error需卸載干凈再重新安裝

2. smi提示[NOT SUPPORTED]

https://github.com/CFSworks/nvml_fix 
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't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.
禁用掉UEFI secure boot
5.提示Failed to initialize NVML: could not load NVML library.
確保依賴都安裝好后,可以重新安裝驅動試試

6.卸載不掉

nvidia-installer --uninstall

7.reboot后發現驅動沒了

查看內核模型沒有加載,dpkg已經安裝相應的package
嘗試使用modprode發現沒有對應內核模塊
內核自動升級了,而安裝驅動的時候沒有設置driver伴隨內核升級.run --dkms

nvidia-docker安裝:

需要添加源,不用FQ
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
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://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-repo-ubuntu1804_10.1.243-1_amd64.deb
    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://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
    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://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
        sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
        sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub 
        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://developer.nvidia.com/cuda-toolkit-archive
            sh cuda_10.1.243_418.87.00_linux.run --toolkit --silent
        wget http://developer.download.nvidia.com/compute/cuda/11.0.1/local_installers/cuda_11.0.1_450.36.06_linux.run
        wget https://developer.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.105_418.39_linux.run
        wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda_10.1.243_418.87.00_linux.run
        注意對driver版本的要求
            https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html

        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://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub 
            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://developer.download.nvidia.cn/compute/machine-learning/repos/ubuntu1804/x86_64/libnccl2_2.7.8-1+cuda10.1_amd64.deb
                wget https://developer.download.nvidia.cn/compute/machine-learning/repos/ubuntu1804/x86_64/libnccl-dev_2.7.8-1+cuda10.1_amd64.deb
        關鍵: 
            需要設置啟動的環境變量
            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           # 第一個負責加載interface,第二個負責ibstat
啟動服務(不一定有該服務,只要內核模塊加載就行)(安裝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方式:
    下載驅動,安裝,然后掛載設備--cap-add=IPC_LOCK --device=/dev/infiniband/uverbs1或--privileged

開機自動配置:
    /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        # 如果掛載中,會提示Device or resource busy
sudo zpool list
sudo zfs set mountpoint=/var/wwwfiles                    # 默認掛載路徑是/files,可以自定義
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        # 小而快速的硬盤,用於slog,最新寫入數據存儲於此
zpool add tank log mirror ada3 ada4        # 多個log備份
zpool add tank cache ada3        # 讀操作的緩存,頻繁讀取的

連接wifi
apt install wireless-tools
iwconfig
ifconfig wlp5s0 up
iwlist wlp5s0 scan | grep ESSID        # 查看wifi列表

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
ip addr show wlp5s0        # 查看ip 
dhclient wlp5s0 -r        # 釋放ip

開機啟動和固定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    # 修改start項
    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

# 地址不一定要ping的通,因為ping協議需要開通端口

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=10允許)    修改完成后執行sysctl -p使新配置生效。

        防火牆禁止;iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -j DROP
              允許: iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
                     iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT

內網dns服務器搭建:

內置的system-resolved:

配置:
systemd-resolve --status查看
默認配置通過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://blog.csdn.net/yangxuan0261/article/details/74907034
https://www.jianshu.com/p/5082e44803e9

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 reverseand the root hints
修改/etc/bind/named.conf.options文件:
    forwarders {
        8.8.8.8;
        114.114.114.114;
    };
    dnssec-validation no;       # 關鍵點,因為本地創建的zone沒有dnssec認證,無論是否定義了local配置
如果需要添加自定義解析,修改/etc/bind/named.conf.local文件:
    zone "example.com" {
        type master;
        file "/etc/bind/db.example.com";
    };
    zone "1.168.192.in-addr.arpa" {             # 局域網ip的倒序
        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                # 每次改變zone文件,該數字需要增加
                             604800         ; Refresh
                              86400         ; Retry
                            2419200         ; Expire
                             604800 )       ; Negative Cache TTL

    @       IN      NS      ns.example.com.                         # 注意結尾有點號.,NS記錄,必須指向A記錄,用來定義ns.example.com是example.com的提供zone復制的servers
    @       IN      A       192.168.1.10                            # 這里替換為自己的局域網ip,添加一條A記錄,將ip映射為hostname
    @       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            # 每次改變zone文件,該數字需要增加
                             604800         ; Refresh
                              86400         ; Retry
                            2419200         ; Expire
                             604800 )       ; Negative Cache TTL
    ;
    @       IN      NS      ns.
    10      IN      PTR     ns.example.com.         # 注意要對應局域網ip的第四位,每在db.example.com添加一條A記錄,都需要在db.192添加一條對應的PTR記錄
重啟服務systemctl restart bind9.service 
    bind服務可以通過本機器的所有網絡接口的ip進行訪問,比如192.168.1.18710.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                  #設置自動啟動eth0接口 eth0 根據實際情況名字不同 根據 ifconfig查看
    iface eth0 inet static     #配置靜態IP
    address 192.168.11.88      #你的IP地址
    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 #當地dns服務器
    # 這個比較重要
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                # 進行ping掃描,打印出對掃描做出響應的主機
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
    #!/bin/bash
    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     # destop和server都有
            service network-manager  status     # 只有destop版本才有。

        /etc/netplan/50-cloud-init.yaml

        network:
          version: 2
          renderer: networkd            # 桌面版用NetworkManager,server版填networkd,填錯了好像也能用
          ethernets:
            ens33:   #配置的網卡名稱
              dhcp4: no    #dhcp4關閉
              dhcp6: no    #dhcp6關閉
              addresses: [192.168.1.55/24]   #設置本機IP及掩碼
              gateway4: 192.168.1.254        #設置網關,可選
              nameservers:
                  addresses: [114.114.114.1148.8.8.8]   #設置DNS

        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.111443端口的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.3192.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  # 單網卡可以填127.0.0.1,多網卡要填對應的ip

                如果機器內轉發,那么是輸出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       # 還需要對POSTROUTING進行配置,可能是源ip轉換的問題。

                抓包看進來請求:
                    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  # 從eno2出去,回來的時候eno2的路由器識別不了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
                # iptables -t nat -A POSTROUTING ! -d 192.168.0.0/16 -o eth1 -j MASQUERADE      # 適合只有一個外網網卡

            思路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      # to表示要去哪里
                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        # 標記了 3 的數據使用table3 路由表
                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     # from表示從哪個網卡發出
                如果還需特殊的條件,比如從某個網卡出來,能夠訪問本網卡的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 --name=unifi-controller -e PUID=1000 -e PGID=1000 -p 3478:3478/udp -p 10001:10001/udp -p 8080:8080   -p 8443:8443 
         -v /data/unifi:/config --restart unless-stopped  linuxserver/unifi-controller
    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 --now libvirtd

配置界面連接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 --state RELATED,ESTABLISHED -j ACCEPT
            iptables -A FORWARD -i virbr0 -o br0 -j ACCEPT
            iptables -I FORWARD 1 -i br0 -o br0 -j ACCEPT

            # 然后正常啟動,通過arp -an | grep 52:54:00:ce:8a:c4查看ip

            如何恢復:
                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 --active
            nmcli conn up br0           # 目前在這步失敗了Error: Connection activation failed: Connection 'bridge-br0' is not available on the device br0 at this time.
            nmcli conn down eno1
            nmcli conn show --active    

            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-type=kvm --name=ubuntu1804 --ram=2048 --vcpus=4 --os-variant=ubuntu18.04 --hvm --graphics vnc
        --cdrom=/var/lib/libvirt/boot/ubuntu-18.04.5-live-server-amd64.iso \
        --network=default       # 默認網絡nat只能連宿主機,bridge=br0使用橋接網絡
        --disk path=/var/lib/libvirt/images/ubuntu1804.qcow2,size=40,bus=virtio,format=qcow2
        # --disk path=default,size=40,bus=virtio,format=qcow2

    virt-install --hvm --name=ubuntu1804-amd-2 --ram=2048 --vcpus=4 --arch=x86_64 --os-variant=ubuntu18.04 --cdrom=/mnt/bigdisk3/ubuntu-18.04.1-server-amd64.iso 
        --network=default --graphics vnc --disk path=/mnt/bigdisk3/ubuntu1804-amd-2.qcow2,size=40,bus=virtio,format=qcow2

    # 注意不能tmp目錄,文件系統類型不允許,還要注意iso和disk的路徑權限

3.常用命令:
    virsh list
    virsh shutdown/start/suspend/reboot/reset/undefine/destroy/console/edit xxx
    virt-viewer ukvm1404

    存儲pool相關:
        virsh pool-list --all
        virsh pool-define-as kvmpool --type dir --target /data/kvm/pool
        virsh pool-list --all
        virsh pool-start kvmpool
        virsh pool-autostart kvmpool

    加盤
        qemu-img create -f raw ubuntu-vm-disk-100G-1 100G       # 如果size不對換為raw
        virsh attach-disk ubuntu-box1 /var/lib/libvirt/images/ubuntu-box1-vm-disk1-5G vdb --cache none
        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     # fdisk看到生效
            resize2fs /dev/vda2     # df -h才能看到生效
            lsblk 

    內存和cpu:
        編輯命令是可以的
            virsh edit xxx 
        圖形化界面操作
        命令行操作:
            virsh dominfo CentOS6_1| grep mem
            virsh setmaxmem 2 --size 16384304 --live        # 當使用內存不超過最大內存時,用這個可以不停機增加內存
            virsh setmaxmem 2 --size 16384304 --current
            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 --domain pxe --type bridge --source br1 --model virtio --config --live 
        virsh detach-interface --domain pxe --type bridge --mac 52:54:00:47:2f:eb --config

        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.0192.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地址(原理同23步,主機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 10101001 00-E0-4C-11-11-11
    B 10101002 00-E0-4C-22-22-22
    C 10102003 00-E0-4C-33-33-33
    首先攻擊方C修改IP包的生存時間,將其延長,以便做充足的廣播。然后和上面提到的一樣,尋找主機B的漏洞,攻擊此漏洞,使主機B暫時無法工作。
    此后,攻擊方C發送IP地址為B的IP地址10101002,MAC地址為C的MAC地址00-E0-4C-33-33-33的ARP應答給A。A接收到應答后,更新其ARP緩存。這樣,在主機A上B的IP地址就對應C的MAC地址。
    但是,A在發數據包給B時,仍然會在局域網內尋找10101002的MAC地址,不會把包發給路由器,這時就需要進行ICMP重定向,告訴主機A到10101002的最短路徑不是局域網,而是路由,請主機重定向路由路徑,
    把所有到10101002的包發給路由器。主機A在接受到這個合理的ICMP重定向后,修改自己的路由路徑,把對10101002的數據包都發給路由器。這樣攻擊方C就能得到來自內部網段的數據包。


ubuntu下相關工具:
    arping
        arping 192.168.131.155  # 查看mac地址
        arping -c 3 192.。168.0.106  # 指定請求次數
        arping -S 10.31.3.251 10.31.3.110   # 設定arping發送的arp數據包中的源地址,好像沒有欺騙的效果
    dsniff
        arpspoof -i enp98s0f0 -t 192.168.66.21 192.168.66.197       # t指定target,對目標進行欺騙

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文件
    #./clean-all
    ./easyrsa init-pki
生成根證書和密鑰ca.crt ca.key 
    #build-ca
    ./easyrsa build-ca nopass       # 回車即可
生成服務器證書和密鑰
    #build-key-server server
    ./easyrsa gen-req server nopass
    ./easyrsa sign server server
生成客戶端證書和密鑰
    #build-key client
    ./easyrsa gen-req client nopass
    ./easyrsa sign client client
生成密鑰交換文件
    #build-dh
    ./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 --genkey --secret ta.key
    cp ta.key ./keys/
啟動openvpn服務
    openvpn --daemon --config server.conf
    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 .    # 如果不同服務器,從server上拷貝
    修改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 --config ~/openvpn-2.5.0/client.conf --daemon
        查看本地ifconfig是否分配了ip

如何訪問沒有設置網關的局域網機器(客戶端連接后默認沒有網關):
    配置iptables的nat功能
    iptables -P FORWARD ACCEPT
    iptables -I INPUT -p tcp --dport 1194 -m comment --comment "openvpn" -j ACCEPT  
    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        # 這個設置后,連普通的路由10.1.0.1 via 10.1.0.5 dev tun0也不會設置。從服務器同步route會報錯,但不影響。
        route 0.0.0.0 0.0.0.0
        route 外網ip 255.255.255.255 net_gateway      # 外網才需要,否則可以走已經加上的route,比如192.168.0.0.21

    原理:
        重啟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         # 決定了0.0.0.0-127.255.255.254的ip走tun0
        10.1.0.1 via 10.1.0.5 dev tun0          # 網關ip走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       # 128.0.0.1-255.255.255.254的ip走tun0
        58.250.250.126 via 192.168.1.1 dev ens3 # server所在ip走本地網卡,例外情況。如果用的是內網,也會添加,不過會報Linux route add command failed,因為與現有route沖突了。

    dns好像沒問題,可以正常解析,但不是通過10.8.0.1

條件路由:
    client.conf添加
        route-nopull                                        # 很重要,可以讓客戶端不同步服務器的全局代理配置,這樣才能實現條件路由
        route 202.120.127.0 255.255.255.0 vpn_gateway       # 所有該網段范圍的ip都走該路由

    重啟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 --to 10.8.0.1
                    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 --to 10.8.0.1
            替換為
                iptables -t nat -A PREROUTING -s 10.1.0.0/24 -p tcp ! --dport 53 -j DNAT --to 10.8.0.1
                iptables -t nat -A PREROUTING -s 10.1.0.0/24 -p udp ! --dport 53 -j DNAT --to 10.8.0.1
                iptables -t nat -A PREROUTING -s 10.1.0.0/24 -p icmp -j DNAT --to 10.8.0.1              # ping遵循的協議,能夠讓C機器ping通
        解決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 --dport 443 -j DNAT --to 10.1.0.1
                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://github.com/coreos

[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)信號。
# 發出的信號都會造成當前運行的進程暫停,CPU掛起,處理該信號完畢后再繼續
常見信號:
    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       # 需注意主線程有沒有空閑來處理,time.sleep(1)
    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 才是文件刪除的必要條件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM