SSH命令總結


一、ssh命令

登錄類型

  1. 密碼登錄: 服務器發送公鑰給客戶端,客戶端使用公鑰加密后回傳給服務器,服務器解密驗證密碼。
  2. 公鑰登錄: 服務器發送一個隨機字符串給客戶端,客戶端用私鑰加密,服務器用公鑰解密(rsa作為簽名使用)

ssh命令相關參數

  1. -A 密鑰轉發 這個參數在使用跳板機等場景非常有用,如果發現始終連不上需要檢查下這個
  2. -i 指定密鑰文件
  3. -p 端口號
  4. -C:請求壓縮所有數據;
  5. -f 后台運行
  6. -N 參數: 不要求分配shell,有些場景下ssh禁止賬號請求shell終端,比如這個賬號只是作為轉發
  7. -g 默認這個LocalPort端口只允許本機連接,可以通過這個參數允許別的機器連接這個端口
  8. -T :不要求分配終端
  9. -o ServerAliveInterval=60 隔段時間發送保活消息
  10. -q 抑制一些調試性的額外輸出
  11. -v 顯示詳細的調試信息,如果ssh連不上可以使用這個參數看看哪一步出問題了

相關的命令

  1. ssh-keygen 用於生成密鑰對
  2. ssh-copy-id 用於復制公鑰到服務器

復制公鑰也可以使用:ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub


相關的文件

  1. ~/.ssh/authorized_keys 用於保存用戶的公鑰文件
  2. ~/.ssh/known_hosts文件 保存的服務器用於辨別服務器的唯一散列碼
  3. ~/.ssh/id_dsa 用戶的私鑰文件
  4. ~/.ssh/id_rsa.pub 默認生成的用戶的公鑰文件,用於將該公鑰追加到需要登錄的服務器authorized_keys文件
  5. /etc/ssh/ssh_config 客戶端ssh配置
  6. /etc/ssh/sshd_config 服務端ssh配置

使用模式

這里推薦一種使用的模式,在利用腳本做自動化的時候,可以利用ssh操作遠程主機,這種方式可以靈活的運用管道,使用了重定向,如上面修改authorized_keys。例:

將遠程主機$HOME/src/目錄下面的所有文件,復制到用戶的當前目錄:ssh user@host 'tar cz src' | tar xzv

將$HOME/src/目錄下面的所有文件,復制到遠程主機的$HOME/src/目錄: cd && tar czv src | ssh user@host 'tar xz'

二、端口轉發

動態轉發ssh -D 1080 user@host -Nfg

最廣泛的用途是作為sock5代理,另外還有加密連接的附加好處,廣泛使用的ss軟件就是用的這個。
另外還可以作為跳板機實現,公網的服務器有些沒有外網ip,通過有外網的服務器作為代理去訪問那些只有內網ip的服務器。


本地轉發ssh -L LocalPort:remoteHost:remotePort sshHost
注意這里remoteHost:remotePort是相對於sshHost的地址,比如remoteHost設置為localhost,實際就是sshHost本地

一般用於無法直連的場景,比如防火牆,沒有開發公網端口等, 本地不能直接連接remoteHost,需要用sshHost來做中轉。
當時我們公司的一個場景,我們的服務器一些后台沒有開通外網端口,在公司內部我們需要訪問后台,利用內網的一台服務器ssh本地轉發到公網服務器,我們在內網直接訪問內網服務器。


遠程轉發ssh -R LocalPort:remoteHost:remotePort sshHost

注意這里remoteHost:remotePort是相對於ssh命令執行的機器的和本地轉發不同。
另外注意這個命令執行和機器和本地轉發不同。比如我們有這么個需求,將服務器serverA的21端口映射到client的2021。
本地轉發:這時我們在客戶機上執行本地轉發命令,ssh -L 2021:localhost:21 serverA
遠程轉發: 則是在服務器上運行,ssh -R 2021:localhsot:21 client,client指的是我們的客戶機,也就是說client需要有sshServer

上面的本地轉發和遠程轉發很像,同樣的功能命令差在一個參數,但兩者有時候不可相互取代。本地和遠程從數據的出口來記:
本地:客戶端連接sshServer將本地的數據轉發到本地端口轉發出去
遠程: 客戶端連接sshServer,在sshServer建立端口,數據從sshServer到本地來

一般用於公網訪問局域網的場景。在局域網的機器建立遠程轉發讓公網的服務器可以訪問局域網

xsell中 菜單->查看—>隧道窗格中可以快速創建這三種類型。


三、跳板機登錄

很多時候線上服務器的權限管理是通過跳板機來控制的,比如服務器a,b,c你不能直接連接,而是通過先登錄跳板機再去連接。如果你現在想在本地連接服務器,有如下方案:

  1. 在本地使用動態轉發,如ssh -D 1080 user@host 主機和用戶使用的是跳板機,在xshell中新建連接時使用1080作為代理,此時你可以將這個連接認為是跳板機在連,比如你在連接中填寫localhost,這個localhost到時就是跳板機
  2. 在本地使用本地轉發,如ssh -L 2222:hosta:22 tiaobanHost,這時候我們就可以使用localhost和2222端口在連接服務器a,不需要配置代理
  3. 遠程轉發一般不用,因為服務器不能訪問公司的局域網

上面的方法雖然可以實現登錄后端服務器,但是兩部操作還是有些不便,可以使用更方便的ProxyCommand。

該方法也有兩種形式:

  1. ssh -o ProxyCommand="ssh user@jumpHost -W %h:%p" serverHost
  2. ssh -o ProxyCommand="nc -x jumpHost:jumpPort %h:%p" serverHost

這個命令如果經常使用可以將ProxyCommand寫入到ssh的配置文件中

現在有三個機器

  1. 客戶機:192.168.199.3
  2. 跳板機:192.168.199.6
  3. 目標機:192.168.199.5

第一種執行:ssh -o ProxyCommand="ssh 192.168.199.6 -W %h:%p" 192.168.199.5

注意這個-W是在新版中才加入,openssh 5.4之后才支持,相當於簡化版的nc

客戶機進程:

chen      50607  50529  0 17:52 pts/0    00:00:00 ssh -o ProxyCommand=ssh 192.168.199.6 -W %h:%p 192.168.199.5
chen      50608  50607  0 17:52 pts/0    00:00:00 ssh 192.168.199.6 -W 192.168.199.5:22

客戶機顯示的連接:

tcp        0      0 192.168.199.3:34306     192.168.199.6:22        ESTABLISHED 50608/ssh

跳板機顯示的連接:

tcp        0      0 192.168.199.6:36932     192.168.199.5:22        ESTABLISHED -                   
tcp        0      0 192.168.199.6:22        192.168.199.3:34306     ESTABLISHED - 

目標機顯示的連接:

tcp        0      0 192.168.199.5:22        192.168.199.6:36932     ESTABLISHED - 

從上面的結果可以看到,跳板機和兩頭各建立了一個連接,另外客戶機是50608進程占用了這個連接


第二種執行:ssh -o ProxyCommand="ssh 192.168.199.6 nc %h %p" 192.168.199.5

這種方式和方面的一樣,顯示的連接也都一致。


最后說說一種nc

注意這種方式需要有個sock5代理,所以跳板機先開啟代理:ssh -D 4000 192.168.199.5 -Nfg
nc支持多種代理,包活scok4,sock5和http,這種方式和上面的兩種完全不同。有一點很奇怪如果跳板機沒開sock5代理也沒有任何報錯信息,ssh並沒有
並沒有使用代理而是直接連接目標服務器
ssh -o ProxyCommand="nc -x 192.168.199.6:4000 %h %p" 192.168.199.5

四、scp 命令

例子:scp test.txt chen@centos:/home/chen/data/

  1. -P 指明端口
  2. -r 遞歸復制
  3. -i 指明密鑰文件

五、rsync命令

例子: rsync -avuz ~test/ chen@centos:/home/chen/data/

rsync命令和scp類似,主要是采用'rsync'算法只同步不同的文件,支持壓縮傳輸和斷點續傳,一般情況下速度更快。參數如下:

  1. -t 不更新modify time
  2. -z 壓縮
  3. -P 斷點續傳功能,大文件用到
  4. -r 遞歸傳遞
  5. -I 強制同步
  6. -a 歸檔模式並保持所有文件屬性, 等價於-rlptgoD (no -H,-A,-X)
  7. -v 輸出傳輸詳情
  8. -u 如果接受者上的文件比傳輸者的新舊不同步

指定端口,如1280端口: rsync -ravuz -e 'ssh -p 1280' 192.168.10.10:/home/chenfangzhi/ .
另外rsync還有一種服務器模式,采用rsync服務端和客戶端的模型,需要長期同步文件,推薦使用這種模式,這種模式的賬號和linux系統賬號是分開的,更加安全。

六、 ssh-agent

最后說的這個東西是非常有用的,如果經常使用的ssh的肯定會遇到需要用多個私鑰的場景和私鑰被加密的場景。如果私鑰被加密,每次連接還是需要輸入密碼,
當在各個服務器之間穿可能需要多次id_rsa密碼,很是繁瑣,另外多個多個主機采用不同的私鑰的時候需要指定私鑰,ssh-agent就是用來解決這個問題的。

這個功能需要在sshd配置文件中配置AllowAgentForwarding,ssh配置文件中配置ForwardAgent

  1. eval `ssh-agent -s` :開啟agent,這里必須使用eval
  2. ssh-add id_rsa_file:用來添加密鑰,這里如果不指定文件則添加的是~/.ssh/id_rsa文件

七、ssh執行命令不退出問題

我們在批量執行服務器命令經常會用到ssh host command命令,但是在有時候發現這個命令不能正常退出,說下這種模式下命令正常退出的條件:

  1. 遠程的執行的進程執行完成或者放入后台運行
  2. 如果是放入后台運行要保證該進程或子進程的標准輸入輸出和當前ssh進程沒有聯系

這種問題經常出現的場景是,我去批量啟動服務器上的服務,調用start.sh腳本之后(ssh host "bash start.sh &"),發現無法退出。這時候我采用了
ssh host "nohup bash start.sh &",發現還是不能正常退出。最后查了下就是上面的兩個原因,因為start.sh腳本中啟動了新的進程,子進程繼承了bash進程文件描述符,
也就是輸入輸出都和bash相同,和ssh進程還有聯系。所以改寫為:ssh host "bash start.sh &>out.log &"成功運行。
另外說說nohup這個命令,在這里其實nohup是完全沒必要使用的,一方面是因為nohup是為了忽略SIGHUP信號,但是如果是使用ssh host command這種模式的話,進程是不會和終端綁定也就是進程不會
收到SIGHUP信號。另一方面是nohup是在執行的進程的標准輸入和輸出綁定了終端時會重定向,但是這個場景下,標准輸入輸出已經被重定向到了管道。

ssh有個-t參數,如果加入這個參數,則會默認分配一個終端,上面的邏輯就變了,需要使用nohup來進行重定向。但是我發現如果是使用ssh -t host "nohup bash start.sh &>out.log &"啟動進程還會導致進程無法啟動的問題,網上說是ssh進程退出的太快了,導致nohup被殺死。但是&后面不能sleep函數,語法報錯。一種方法是start.sh中啟動服務地方加入&,然后上面改寫成ssh -t host "nohup bash start.sh &>out.log;sleep 1"

重定向的問題參看上面紅字

我在虛擬機的實驗結果如下:

[chen@cc1 ~]$ ssh root@192.168.199.5  "TMPSPID=\$(ps -ef | grep -v grep |grep -e 'sshd.*notty' | awk '{print \$2}');echo \$TMPSPID;ls -l /proc/\$TMPSPID/fd;echo \$\$;ls -l /proc/\$\$/fd"
root@192.168.199.5's password: 
14719
total 0
lrwx------. 1 root root 64 May 28 21:37 0 -> /dev/null
lrwx------. 1 root root 64 May 28 21:37 1 -> /dev/null
l-wx------. 1 root root 64 May 28 21:37 11 -> pipe:[122988]
lr-x------. 1 root root 64 May 28 21:37 12 -> pipe:[122989]
lr-x------. 1 root root 64 May 28 21:37 14 -> pipe:[122990]
lrwx------. 1 root root 64 May 28 21:37 2 -> /dev/null
lrwx------. 1 root root 64 May 28 21:37 3 -> socket:[122854]
lrwx------. 1 root root 64 May 28 21:37 4 -> socket:[122951]
lr-x------. 1 root root 64 May 28 21:37 5 -> pipe:[122954]
l-wx------. 1 root root 64 May 28 21:37 6 -> /run/systemd/sessions/94.ref
l-wx------. 1 root root 64 May 28 21:37 7 -> pipe:[122954]
14725
total 0
lr-x------. 1 root root 64 May 28 21:37 0 -> pipe:[122988]
l-wx------. 1 root root 64 May 28 21:37 1 -> pipe:[122989]
l-wx------. 1 root root 64 May 28 21:37 2 -> pipe:[122990]

八、sz和rz命令

這兩個命令十分方便,在Windows下使用xshell客戶端,如果遇到跳板機這種場景,需要頻繁的穿來穿去,這兩個命令可以自動穿隧道,十分方便,命令本省十分簡單。

  1. -e 采用二進制傳輸,這個非常重要,有時候在傳輸可執行文件時
  2. -y 如果存在則覆蓋原文件,默認是生成一個

參考文章

  1. SSH原理與運用(一):遠程登錄
  2. SSH原理與運用(二):遠程操作與端口轉發
  3. Linux ssh命令詳解
  4. ssh -W and ssh nc
  5. ssh遠程執行nohup命令不退出


免責聲明!

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



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