ssh連接遠(yuǎn)程主機(jī)執(zhí)行腳本的環(huán)境變量問題

image.png

近日在使用ssh命令ssh user@remote ~/myscript.sh 登陸到遠(yuǎn)程機(jī)器remote上執(zhí)行腳本時(shí)杀怠,遇到一個(gè)奇怪的問題:
~/myscript.sh: line n: app: command not found
app是一個(gè)新安裝的程序,安裝路徑明明已通過/etc/profile配置文件加到環(huán)境變量中,但這里為何會(huì)找不到蹋订?如果直接登陸機(jī)器remote并執(zhí)行~/myscript.sh時(shí),app程序可以找到并順利執(zhí)行刻伊。但為什么使用了ssh遠(yuǎn)程執(zhí)行同樣的腳本就出錯(cuò)了呢露戒??jī)煞N方式執(zhí)行腳本到底有何不同?如果你也心存疑問捶箱,請(qǐng)跟隨我一起來展開分析智什。

說明,本文所使用的機(jī)器是:SUSE Linux Enterprise丁屎。

問題定位


這看起來像是環(huán)境變量引起的問題荠锭,為了證實(shí)這一猜想,我在這條命令之前加了一句:which app晨川,來查看app的安裝路徑证九。在remote本機(jī)上執(zhí)行腳本時(shí),它會(huì)打印出app正確的安裝路徑共虑。但再次用ssh來執(zhí)行時(shí)愧怜,卻遇到下面的錯(cuò)誤:
which: no app in (/usr/bin:/bin:/usr/sbin:/sbin)
這很奇怪,怎么括號(hào)中的環(huán)境變量沒有了app
程序的安裝路徑妈拌?不是已通過/etc/profile 設(shè)置到PATH中了拥坛?再次在腳本中加入echo $PATH并以ssh執(zhí)行,這才發(fā)現(xiàn)供炎,環(huán)境變量仍是系統(tǒng)初始化時(shí)的結(jié)果:
/usr/bin:/bin:/usr/sbin:/sbin

這證明/etc/profile
根本沒有被調(diào)用渴逻。為什么?是ssh命令的問題么音诫?

隨后我又嘗試了將上面的ssh分解成下面兩步:
user@local > ssh user@remote # 先遠(yuǎn)程登陸到remote上user@remote> ~/myscript.sh # 然后在返回的shell中執(zhí)行腳本

結(jié)果竟然成功了惨奕。那么ssh以這兩種方式執(zhí)行的命令有何不同?帶著這個(gè)問題去查詢了man ssh
If command is specified, it is executed on the remote host instead of a login shell.

這說明在指定命令的情況下竭钝,命令會(huì)在遠(yuǎn)程主機(jī)上執(zhí)行梨撞,返回結(jié)果后退出。而未指定時(shí)香罐,ssh會(huì)直接返回一個(gè)登陸的shell卧波。但到這里還是無法理解,直接在遠(yuǎn)程主機(jī)上執(zhí)行和在返回的登陸shell中執(zhí)行有什么區(qū)別庇茫?即使在遠(yuǎn)程主機(jī)上執(zhí)行不也是通過shell來執(zhí)行的么港粱?難道是這兩種方式使用的shell有什么不同?
暫時(shí)還沒有頭緒,但隱隱感到應(yīng)該與shell有關(guān)查坪。因?yàn)槲彝ǔJ褂玫氖莃ash寸宏,所以又去查詢了man bash,才得到了答案偿曙。

bash的四種模式


在man page的INVOCATION一節(jié)講述了bash的四種模式氮凝,bash會(huì)依據(jù)這四種模式而選擇加載不同的配置文件,而且加載的順序也有所不同望忆。本文ssh問題的答案就存在于這幾種模式當(dāng)中罩阵,所以在我們揭開謎底之前先來分析這些模式。

interactive + login shell

第一種模式是交互式的登陸shell启摄,這里面有兩個(gè)概念需要解釋: interactive和login:

login故名思義稿壁,即登陸,login shell是指用戶以非圖形化界面或者以ssh登陸到機(jī)器上時(shí)獲得的第一個(gè)shell鞋仍,簡(jiǎn)單些說就是需要輸入用戶名和密碼的shell常摧。因此通常不管以何種方式登陸機(jī)器后用戶獲得的第一個(gè)shell就是login shell。

interactive意為交互式威创,這也很好理解落午,interactive shell會(huì)有一個(gè)輸入提示符,并且它的標(biāo)準(zhǔn)輸入肚豺、輸出和錯(cuò)誤輸出都會(huì)顯示在控制臺(tái)上溃斋。所以一般來說只要是需要用戶交互的,即一個(gè)命令一個(gè)命令的輸入的shell都是interactive shell吸申。而如果無需用戶交互梗劫,它便是non-interactive shell。通常來說如bash script.sh 此類執(zhí)行腳本的命令就會(huì)啟動(dòng)一個(gè)non-interactive shell截碴,它不需要與用戶進(jìn)行交互梳侨,執(zhí)行完后它便會(huì)退出創(chuàng)建的shell。

那么此模式最簡(jiǎn)單的兩個(gè)例子為:

  • 用戶直接登陸到機(jī)器獲得的第一個(gè)shell
  • 用戶使用ssh user@remote獲得的shell

加載配置文件

這種模式下日丹,shell首先加載/etc/profile走哺,然后再嘗試依次去加載下列三個(gè)配置文件之一,一旦找到其中一個(gè)便不再接著尋找

  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile

下面給出這個(gè)加載過程的偽代碼:

execute /etc/profile
IF ~/.bash_profile exists THEN
    execute ~/.bash_profile
ELSE
    IF ~/.bash_login exist THEN
        execute ~/.bash_login
    ELSE
        IF ~/.profile exist THEN
            execute ~/.profile
        END IF
    END IF
END IF

為了驗(yàn)證這個(gè)過程哲虾,我們來做一些測(cè)試丙躏。首先設(shè)計(jì)每個(gè)配置文件的內(nèi)容如下:

user@remote > cat /etc/profile
echo @ /etc/profile
user@remote > cat ~/.bash_profile
echo @ ~/.bash_profile
user@remote > cat ~/.bash_login
echo @ ~/.bash_login
user@remote > cat ~/.profile
echo @ ~/.profile

然后打開一個(gè)login shell,注意束凑,為方便起見晒旅,這里使用bash -l命令,它會(huì)打開一個(gè)login shell汪诉,在man bash中可以看到此參數(shù)的解釋:
-l Make bash act as if it had been invoked as a login shell

進(jìn)入這個(gè)新的login shell废恋,便會(huì)得到以下輸出:

@ /etc/profile
@ /home/user/.bash_profile

果然與文檔一致,bash首先會(huì)加載全局的配置文件/etc/profile,然后去查找~/.bash_profile拴签,因?yàn)槠湟呀?jīng)存在孝常,所以剩下的兩個(gè)文件不再會(huì)被查找。接下來移除~/.bash_profile蚓哩,啟動(dòng)login shell得到結(jié)果如下:

@ /etc/profile
@ /home/user/.bash_login

因?yàn)闆]有了~/.bash_profile的屏蔽,所以~/.bash_login被加載上渴,但最后一個(gè)~/.profile仍被忽略岸梨。再次移除~/.bash_login,啟動(dòng)login shell的輸出結(jié)果為:

@ /etc/profile
@ /home/user/.profile

~/.profile終于熬出頭稠氮,得見天日曹阔。通過以上三個(gè)實(shí)驗(yàn),配置文件的加載過程得到了驗(yàn)證隔披,除去/etc/profile首先被加載外赃份,其余三個(gè)文件的加載順序?yàn)椋?code>~/.bash_profile > ~/.bash_login > ~/.profile,只要找到一個(gè)便終止查找奢米。

前面說過抓韩,使用ssh也會(huì)得到一個(gè)login shell,所以如果在另外一臺(tái)機(jī)器上運(yùn)行ssh user@remote時(shí)鬓长,也會(huì)得到上面一樣的結(jié)論谒拴。

配置文件的意義
那么,為什么bash要弄得這么復(fù)雜涉波?每個(gè)配置文件存在的意義是什么英上?

/etc/profile很好理解,它是一個(gè)全局的配置文件啤覆。后面三個(gè)位于用戶主目錄中的配置文件都針對(duì)用戶個(gè)人苍日,也許你會(huì)問為什么要有這么多,只用一個(gè)~/.profile不好么窗声?究竟每個(gè)文件有什么意義呢相恃?這是個(gè)好問題。

Cameron Newham和Bill Rosenblatt在他們的著作《Learning the bash Shell, 2nd Edition》的59頁解釋了原因:

bash allows two synonyms for .bash_profile: .bash_login, derived from the C shell’s file named .login, and .profile, derived from the Bourne shell and Korn shell files named .profile. Only one of these three is read when you log in. If .bash_profile doesn’t exist in your home directory, then bash will look for .bash_login. If that doesn’t exist it will look for .profile.
One advantage of bash’s ability to look for either synonym is that you can retain your .profile if you have been using the Bourne shell. If you need to add bash-specific commands, you can put them in .bash_profile followed by the command source .profile. When you log in, all the bash-specific commands will be executed and bash will source .profile, executing the remaining commands. If you decide to switch to using the Bourne shell you don’t have to modify your existing files. A similar approach was intended for .bash_login and the C shell .login, but due to differences in the basic syntax of the shells, this is not a good idea.

原來一切都是為了兼容嫌佑,這么設(shè)計(jì)是為了更好的應(yīng)付在不同shell之間切換的場(chǎng)景豆茫。因?yàn)閎ash完全兼容Bourne shell,所以.bash_profile.profile可以很好的處理bash和Bourne shell之間的切換屋摇。但是由于C shell和bash之間的基本語法存在著差異揩魂,作者認(rèn)為引入.bash_login并不是個(gè)好主意。所以由此我們可以得出這樣的最佳實(shí)踐:

  • 應(yīng)該盡量杜絕使用.bash_login炮温,如果已經(jīng)創(chuàng)建火脉,那么需要?jiǎng)?chuàng)建.bash_profile來屏蔽它被調(diào)用
  • .bash_profile適合放置bash的專屬命令,可以在其最后讀取.profile,如此一來,便可以很好的在Bourne shell和bash之間切換了

non-interactive + login shell

第二種模式的shell為non-interactive login shell倦挂,即非交互式的登陸shell畸颅,這種是不太常見的情況。一種創(chuàng)建此shell的方法為:bash -l script.sh,前面提到過-l參數(shù)是將shell作為一個(gè)login shell啟動(dòng)方援,而執(zhí)行腳本又使它為non-interactive shell没炒。

對(duì)于這種類型的shell,配置文件的加載與第一種完全一樣犯戏,在此不再贅述送火。

interactive + non-login shell

第三種模式為交互式的非登陸shell,這種模式最常見的情況為在一個(gè)已有shell中運(yùn)行bash, 此時(shí)會(huì)打開一個(gè)交互式的shell先匪,而因?yàn)椴辉傩枰顷懼治虼瞬皇莑ogin shell。

加載配置文件

對(duì)于此種情況呀非,啟動(dòng)shell時(shí)會(huì)去查找并加載/etc/bash.bashrc~/.bashrc文件坚俗。
為了進(jìn)行驗(yàn)證,與第一種模式一樣岸裙,設(shè)計(jì)各配置文件內(nèi)容如下:

user@remote > cat /etc/bash.bashrc
echo @ /etc/bash.bashrc
user@remote > cat ~/.bashrc
echo @ ~/.bashrc

然后我們啟動(dòng)一個(gè)交互式的非登陸shell猖败,直接運(yùn)行bash即可,可以得到以下結(jié)果:

@ /etc/bash.bashrc
@ /home/user/.bashrc

由此非常容易的驗(yàn)證了結(jié)論哥桥。
bashrc VS profile
從剛引入的兩個(gè)配置文件的存放路徑可以很容易的判斷辙浑,第一個(gè)文件是全局性的,第二個(gè)文件屬于當(dāng)前用戶拟糕。在前面的模式當(dāng)中判呕,已經(jīng)出現(xiàn)了幾種配置文件,多數(shù)是以profile命名的送滞,那么為什么這里又增加兩個(gè)文件呢侠草?這樣不會(huì)增加復(fù)雜度么?我們來看看此處的文件和前面模式中的文件的區(qū)別犁嗅。

首先看第一種模式中的profile類型文件边涕,它是某個(gè)用戶唯一的用來設(shè)置全局環(huán)境變量的地方, 因?yàn)橛脩艨梢杂卸鄠€(gè)shell比如bash, sh, zsh等, 但像環(huán)境變量這種其實(shí)只需要在統(tǒng)一的一個(gè)地方初始化就可以, 而這個(gè)地方就是profile,所以啟動(dòng)一個(gè)login shell會(huì)加載此文件褂微,后面由此shell中啟動(dòng)的新shell進(jìn)程如bash功蜓,sh,zsh等都可以由login shell中繼承環(huán)境變量等配置宠蚂。
接下來看bashrc式撼,其后綴rc的意思為Run Commands,由名字可以推斷出求厕,此處存放bash需要運(yùn)行的命令著隆,但注意扰楼,這些命令一般只用于交互式的shell,通常在這里會(huì)設(shè)置交互所需要的所有信息美浦,比如bash的補(bǔ)全弦赖、alias、顏色浦辨、提示符等等蹬竖。

所以可以看出,引入多種配置文件完全是為了更好的管理配置流酬,每個(gè)文件各司其職案腺,只做好自己的事情。

non-interactive + non-login shell

最后一種模式為非交互非登陸的shell康吵,創(chuàng)建這種shell典型有兩種方式:

  • bash script.sh
  • ssh user@remote command

這兩種都是創(chuàng)建一個(gè)shell,執(zhí)行完腳本之后便退出访递,不再需要與用戶交互晦嵌。

加載配置文件

對(duì)于這種模式而言,它會(huì)去尋找環(huán)境變量BASH_ENV拷姿,將變量的值作為文件名進(jìn)行查找惭载,如果找到便加載它。

同樣响巢,我們對(duì)其進(jìn)行驗(yàn)證描滔。首先,測(cè)試該環(huán)境變量未定義時(shí)配置文件的加載情況踪古,這里需要一個(gè)測(cè)試腳本:

user@remote > cat ~/script.sh
echo Hello World

然后運(yùn)行bash script.sh含长,將得到以下結(jié)果:
Hello World

從輸出結(jié)果可以得知,這個(gè)新啟動(dòng)的bash進(jìn)程并沒有加載前面提到的任何配置文件伏穆。接下來設(shè)置環(huán)境變量BASH_ENV:

user@remote > export BASH_ENV=~/.bashrc

再次執(zhí)行bash script.sh拘泞,結(jié)果為:

@ /home/user/.bashrc
Hello World

果然,~/.bashrc被加載枕扫,而它是由環(huán)境變量BASH_ENV 設(shè)定的陪腌。

更為直觀的示圖


至此,四種模式下配置文件如何加載已經(jīng)講完烟瞧,因?yàn)樯婕暗呐渲梦募行┒嗍迹覀冊(cè)僖詢蓚€(gè)圖來更為直觀的進(jìn)行描述:
第一張圖來自這篇文章,bash的每種模式會(huì)讀取其所在列的內(nèi)容参滴,首先執(zhí)行A强岸,然后是B,C卵洗。而B1请唱,B2和B3表示只會(huì)執(zhí)行第一個(gè)存在的文件:

+----------------+--------+-----------+---------------+
|                | login  |interactive|non-interactive|
|                |        |non-login  |non-login      |
+----------------+--------+-----------+---------------+
|/etc/profile    |   A    |           |               |
+----------------+--------+-----------+---------------+
|/etc/bash.bashrc|        |    A      |               |
+----------------+--------+-----------+---------------+
|~/.bashrc       |        |    B      |               |
+----------------+--------+-----------+---------------+
|~/.bash_profile |   B1   |           |               |
+----------------+--------+-----------+---------------+
|~/.bash_login   |   B2   |           |               |
+----------------+--------+-----------+---------------+
|~/.profile      |   B3   |           |               |
+----------------+--------+-----------+---------------+
|BASH_ENV        |        |           |       A       |
+----------------+--------+-----------+---------------+

上圖只給出了三種模式弥咪,原因是第一種login實(shí)際上已經(jīng)包含了兩種,因?yàn)檫@兩種模式下對(duì)配置文件的加載是一致的十绑。
另外一篇文章給出了一個(gè)更直觀的圖:

image.png

上圖的情況稍稍復(fù)雜一些聚至,因?yàn)樗褂昧藥讉€(gè)關(guān)于配置文件的參數(shù): --login--rcfile本橙,--noprofile扳躬,--norc,這些參數(shù)的引入會(huì)使配置文件的加載稍稍發(fā)生改變甚亭,不過總體來說贷币,不影響我們前面的討論,相信這張圖不會(huì)給你帶來更多的疑惑亏狰。

典型模式總結(jié)


為了更好的理清這幾種模式役纹,下面我們對(duì)一些典型的啟動(dòng)方式各屬于什么模式進(jìn)行一個(gè)總結(jié):

  • 登陸機(jī)器后的第一個(gè)shell:login + interactive
  • 新啟動(dòng)一個(gè)shell進(jìn)程,如運(yùn)行bash:non-login + interactive
  • 執(zhí)行腳本暇唾,如bash script.sh:non-login + non-interactive
  • 運(yùn)行頭部有如#!/usr/bin/env bash 的可執(zhí)行文件促脉,如./executable:non-login + non-interactive
  • 通過ssh登陸到遠(yuǎn)程主機(jī):login + interactive
  • 遠(yuǎn)程執(zhí)行腳本,如ssh user@remote script.sh:non-login + non-interactive
  • 遠(yuǎn)程執(zhí)行腳本策州,同時(shí)請(qǐng)求控制臺(tái)瘸味,如ssh user@remote -t 'echo $PWD':non-login + interactive
  • 在圖形化界面中打開terminal:
    • Linux上: non-login + interactive
    • Mac OS X上: login + interactive

相信你在理解了login和interactive的含義之后,應(yīng)該會(huì)很容易對(duì)上面的啟動(dòng)方式進(jìn)行歸類够挂。

再次嘗試


在介紹完bash的這些模式之后旁仿,我們?cè)倩仡^來看文章開頭的問題。ssh user@remote ~/myscript.sh屬于哪一種模式孽糖?相信此時(shí)你可以非常輕松的回答出來:non-login + non-interactive枯冈。對(duì)于這種模式,bash會(huì)選擇加載$BASH_ENV的值所對(duì)應(yīng)的文件梭姓,所以為了讓它加載/etc/profile霜幼,可以設(shè)定:

user@remote > export BASH_ENV=/etc/profile

然后執(zhí)行上面的命令,但是很遺憾誉尖,發(fā)現(xiàn)錯(cuò)誤依舊存在罪既。這是怎么回事?別著急铡恕,這并不是我們前面的介紹出錯(cuò)了琢感。仔細(xì)查看之后才發(fā)現(xiàn)腳本myscript.sh的第一行為#!/usr/bin/env sh,注意看探熔,它和前面提到的#!/usr/bin/env bash不一樣驹针,可能就是這里出了問題。我們先嘗試把它改成#!/usr/bin/env bash诀艰,再次執(zhí)行柬甥,錯(cuò)誤果然消失了饮六,這與我們前面的分析結(jié)果一致。

第一行的這個(gè)語句有什么用苛蒲?設(shè)置成sh和bash有什么區(qū)別卤橄?帶著這些疑問,再來查看man bash:
If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the program.

它表示這個(gè)文件的解釋器臂外,即用什么程序來打開此文件窟扑,就好比Windows上雙擊一個(gè)文件時(shí)會(huì)以什么程序打開一樣。因?yàn)檫@里不是bash漏健,而是sh嚎货,那么我們前面討論的都不復(fù)有效了,真糟糕蔫浆。我們來看看這個(gè)sh的路徑:

user@remote > ll `which sh`
lrwxrwxrwx 1 root root 9 Apr 25 2014 /usr/bin/sh -> /bin/bash

原來sh只是bash的一個(gè)軟鏈接殖属,既然如此,BASH_ENV應(yīng)該是有效的啊瓦盛,為何此處無效忱辅?還是回到man bash,同樣在INVOCATION一節(jié)的下部看到了這樣的說明:

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interactive login shell, or a non-interactive shell with the –login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The –noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the –rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.

簡(jiǎn)而言之谭溉,當(dāng)bash以是sh命啟動(dòng)時(shí),即我們此處的情況橡卤,bash會(huì)盡可能的模仿sh扮念,所以配置文件的加載變成了下面這樣:

  • interactive + login: 讀取/etc/profile~/.profile
  • non-interactive + login: 同上
  • interactive + non-login: 讀取ENV環(huán)境變量對(duì)應(yīng)的文件
  • non-interactive + non-login: 不讀取任何文件

這樣便可以解釋為什么出錯(cuò)了,因?yàn)檫@里屬于non-interactive + non-login碧库,所以bash不會(huì)讀取任何文件柜与,故而即使設(shè)置了BASH_ENV
也不會(huì)起作用。所以為了解決問題嵌灰,只需要把sh換成bash弄匕,再設(shè)置環(huán)境變量BASH_ENV即可。

另外沽瞭,其實(shí)我們還可以設(shè)置參數(shù)到第一行的解釋器中迁匠,如#!/bin/bash --login,如此一來驹溃,bash便會(huì)強(qiáng)制為login shell城丧,所以/etc/profile也會(huì)被加載。相比上面那種方法豌鹤,這種更為簡(jiǎn)單亡哄。

配置文件建議


回顧一下前面提到的所有配置文件,總共有以下幾種:

  • /etc/profile
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile
  • /etc/bash.bashrc
  • ~/.bashrc
  • $BASH_ENV
  • $ENV

不知你是否會(huì)有疑問布疙,這么多的配置文件蚊惯,究竟每個(gè)文件里面應(yīng)該包含哪些配置愿卸,比如PATH應(yīng)該在哪?提示符應(yīng)該在哪配置截型?啟動(dòng)的程序應(yīng)該在哪趴荸?等等。所以在文章的最后菠劝,我搜羅了一些最佳實(shí)踐供各位參考赊舶。(這里只討論屬于用戶個(gè)人的配置文件)

  • ~/.bash_profile :應(yīng)該盡可能的簡(jiǎn)單,通常會(huì)在最后加載.profile.bashrc(注意順序)
  • ~/.bash_login:在前面討論過赶诊,別用它
  • ~/.profile:此文件用于login shell笼平,所有你想在整個(gè)用戶會(huì)話期間都有效的內(nèi)容都應(yīng)該放置于此,比如啟動(dòng)進(jìn)程舔痪,環(huán)境變量等
  • ~/.bashrc:只放置與bash有關(guān)的命令寓调,所有與交互有關(guān)的命令都應(yīng)該出現(xiàn)在此,比如bash的補(bǔ)全锄码、alias夺英、顏色、提示符等等滋捶。特別注意:別在這里輸出任何內(nèi)容(我們前面只是為了演示痛悯,別學(xué)我哈)

寫在結(jié)尾


至此,我們?cè)敿?xì)的討論完了bash的幾種工作模式重窟,并且給出了配置文件內(nèi)容的建議载萌。通過這些模式的介紹,本文開始遇到的問題也很容易的得到了解決巡扇。以前雖然一直使用bash扭仁,但真的不清楚里面包含了如此多的內(nèi)容。同時(shí)感受到Linux的文檔的確做得非常細(xì)致厅翔,在完全不需要其它安裝包的情況下乖坠,你就可以得到一個(gè)非常完善的開發(fā)環(huán)境,這也曾是Eric S. Raymond在其著作《UNIX編程藝術(shù)》中提到的:UNIX天生是一個(gè)非常完善的開發(fā)機(jī)器刀闷。本文幾乎所有的內(nèi)容你都可以通過閱讀man page得到熊泵。最后,希望在這樣一個(gè)被妖魔化的特殊日子里甸昏,這篇文章能夠?yàn)槟銕ヒ唤z幫助戈次。

(全文完)
feihu
2014.11.11 于 Shenzhen
來自 http://feihu.me/blog/2014/env-problem-when-ssh-executing-command-on-remote/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市筒扒,隨后出現(xiàn)的幾起案子怯邪,更是在濱河造成了極大的恐慌,老刑警劉巖花墩,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悬秉,死亡現(xiàn)場(chǎng)離奇詭異澄步,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)和泌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門村缸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人武氓,你說我怎么就攤上這事梯皿。” “怎么了县恕?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵东羹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我忠烛,道長(zhǎng)属提,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任美尸,我火速辦了婚禮冤议,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘师坎。我一直安慰自己恕酸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布胯陋。 她就那樣靜靜地躺著尸疆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惶岭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天犯眠,我揣著相機(jī)與錄音按灶,去河邊找鬼。 笑死筐咧,一個(gè)胖子當(dāng)著我的面吹牛鸯旁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播量蕊,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼铺罢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了残炮?” 一聲冷哼從身側(cè)響起韭赘,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎势就,沒想到半個(gè)月后泉瞻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脉漏,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年袖牙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侧巨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鞭达,死狀恐怖司忱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畴蹭,我是刑警寧澤坦仍,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站撮胧,受9級(jí)特大地震影響桨踪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芹啥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一锻离、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧墓怀,春花似錦汽纠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至钓账,卻和暖如春碴犬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梆暮。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工服协, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啦粹。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓偿荷,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親唠椭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跳纳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容