remote_open: ssh終端下一鍵用本地軟件開遠(yuǎn)程文件(夾)

引子

使用ssh連接服務(wù)器臀晃,不可避免會(huì)有用本地的軟件開遠(yuǎn)程文件的需求觉渴,比如查看遠(yuǎn)程圖片,或用本地文本編輯器打開遠(yuǎn)程文件徽惋。

顯然案淋,此時(shí)得將遠(yuǎn)程文件傳達(dá)本地,手段不一而足险绘,scp踢京、sftp、rsycn宦棺、sshfs等等瓣距。然而,不論哪一種代咸,都需要開著兩個(gè)窗口蹈丸,一個(gè)是ssh連接服務(wù)器的終端,一個(gè)是用來敲傳文件命令的終端呐芥。更麻煩的是逻杖,得對著前者的服務(wù)器ip、用戶名思瘟、文件路徑荸百,來敲后者的命令。要知道滨攻,在本地够话,我們只需要輸入open <file_path(s) or dir_path(s)>就能一鍵打開文件(夾)。

為了免去上述體力勞動(dòng)铡买,我實(shí)現(xiàn)了remote open工具,可以像在本地用open命令一樣霎箍,一鍵打開遠(yuǎn)程文件(夾)奇钞。

源代碼:https://github.com/hyliang96/remote_open.git

介紹

功能

ssh連到服務(wù)器后,對著遠(yuǎn)程的終端:

  • 輸入opennc <file_path(s) or dir_path(s)>漂坏,根據(jù)文件后綴本景埃,自動(dòng)選用地軟件,打開遠(yuǎn)程的文件(夾)
  • 輸入 subnc <file_path(s) or dir_path(s)>顶别,用本地sublime谷徙,自動(dòng)打開遠(yuǎn)程的文件(夾)。(你也可以修改代碼驯绎,換成你喜歡的文本編輯器)

本腳本自動(dòng)用sshfs掛載遠(yuǎn)程目錄完慧,無需手動(dòng)同步文件

依賴

  • 服務(wù)器:nc
  • 本地:nc、ssh剩失、sshfs屈尼、zsh

原理

  • ssh連接服務(wù)器册着,并用-R參數(shù)進(jìn)行端口轉(zhuǎn)發(fā),以供nc使用
  • 在遠(yuǎn)程輸入opennc <file_path(s) or dir_path(s)>
  • 遠(yuǎn)程將 [ 【hostname】脾歧、【username】甲捏、<file_path(s) or dir_path(s)>之絕對路徑],由nc發(fā)送到本地
  • 本地偵聽到收到遠(yuǎn)程nc所發(fā)鞭执,按照其要求將<username>@< hostname>:/sshfs掛載到本地
  • 用本地的open打開所目標(biāo)文件(夾)

實(shí)現(xiàn)

遠(yuǎn)程

目的:遠(yuǎn)程將 [ 【hostname】司顿、【username】、<file_path(s) or dir_path(s)>之絕對路徑]兄纺,由nc發(fā)送到本地

在~/.bashrc (或~/.bashrc 會(huì)加載的.bash_aliases大溜、.bash_function)中,添加以下代碼囤热。

subnc(){
    dirs=""
    for arg in $@; do
        if [ -e $arg ]; then
            path_arg=$(abspath $arg)
            dirs="$dirs; $path_arg"
        else
            echo not exist: $arg
        fi
    done
    if [ "${dirs:0:2}" = "; " ]; then
        dirs=${dirs:2}
    fi
    if [ "$dirs" != "" ]; then
        (echo "sub; $USER; `hostname`; $dirs" | nc localhost 【遠(yuǎn)程nc端口】  & )   > /dev/null
    fi
}

opennc(){
    dirs=""
    for arg in $@; do
        if [ -e $arg ]; then
            path_arg=$(abspath $arg)
            dirs="$dirs; $path_arg"
        else
            echo not exist: $arg
        fi
    done
    if [ "${dirs:0:2}" = "; " ]; then
        dirs=${dirs:2}
    fi
    if [ "$dirs" != "" ]; then
        (echo "open; $USER; `hostname`; $dirs" | nc localhost 【遠(yuǎn)程nc端口】  & )   > /dev/null
    fi
}

本地

對sshfs的封裝 -- easy_sshfs

創(chuàng)建 ~/remote_open/easy_sshfs.sh

#!/bin/bash

mount_dir=【自己設(shè)置一個(gè)文件夾猎提,其下專門用來sshfs掛載遠(yuǎn)程目錄】
# --------------------- sshfs --------------------------
# 掛載一個(gè)磁盤
fs() # fs host別名 [遠(yuǎn)端路徑, 默認(rèn)為"."]
{
    if [ "$#" -lt "1" ]; then
        echo "Usage: fs host別名 [遠(yuǎn)端路徑, 默認(rèn)為'.']"
        return
    fi
    host=$1
    if [ "$#" -gt "1" ]; then
        remotepath="$2"
    else
        remotepath="."
    fi
    localpath="$mountdir/${host}"

    if [ "`pgrep -lf sshfs | grep \"$localpath \"`" != "" ]; then
        echo $localpath is already mounted, now remount
        umount $localpath # 若在mount此localpath,則關(guān)閉之
    else
        umount $localpath >/dev/null 2>&1 # 不輸出旁蔼,但任然驗(yàn)證一遍
    fi

    if [ ! -d $localpath ]; then mkdir $localpath; fi # 若無掛載目錄文件夾锨苏,則創(chuàng)建之

    sshfs $host:$remotepath $localpath -o volname=$host -o reconnect -o transform_symlinks -o follow_symlinks
    #  -o local
}
# 卸掛載一個(gè)磁盤
ufs()  # ufs [[用戶名@]host別名 | 用戶名@網(wǎng)址 ] (一個(gè)或多個(gè))
{
    if [ "$#" -lt "1" ]; then
        echo "Usage: fs [[用戶名@]host別名 | 用戶名@網(wǎng)址 ] (一個(gè)或多個(gè))"
        return
    fi

    for host in $@; do
        # host=$1
        localpath="$mountdir/${host}"

        umount $localpath
        if [ "`ls -A $localpath`" = "" ]; then
            rm $localpath -rf # 若掛載目錄是空文件夾,則刪除之
        else
            echo original dir $localpath is now recovered
        fi
    done
}
# 列出目前mount的所有磁盤
fsls()
{
    answer=`pgrep -lf sshfs | awk '{print $1 "  " $3}'`
    if [ "$answer" != "" ]; then echo "pid   host_alias:remote_path"; echo $answer; fi
}
# 列出掛載路徑
mtls()
{
    ls $mountdir -la
}

自動(dòng)掛載遠(yuǎn)程目錄并打開文件

創(chuàng)建 ~/remote_open/remote_open.sh

#!/bin/bash
. ~/remote_open/easy_sshfs.sh
debug=0     # 需要debug輸出設(shè)為1

string="$1"

args=("${(@s/; /)string}")
[ $debug -ne 0 ] && declare -p args

app=${args[1]}
user=${args[2]}
host_alias=${args[3]}
remote_paths=(${args[@]:3:${#args[@]}})

[ $debug -ne 0 ] && echo app: $app
[ $debug -ne 0 ] && echo user: $user
[ $debug -ne 0 ] && echo host_alias: $host_alias
[ $debug -ne 0 ] && declare -p remote_paths


mounts="$(pgrep -lf sshfs | awk '{print $3}')"
mounts=("${(@s/\\n/)mounts}")
[ $debug -ne 0 ] && echo mounts: $mounts

mount_dir=$mountdir
[ $debug -ne 0 ] && echo mount_dir: $mount_dir

mount_folder=$user@$host_alias

if ! [[ ${mounts} =~ $mount_folder:/ ]] || ! [ -d $mount_dir/$host_alias/home ]; then
    [ $debug -ne 0 ] && echo hasnt mounted $mount_folder:/, start mounting
    [ $debug -ne 0 ] && echo fs $mount_folder /
    fs $mount_folder /
    [ $debug -ne 0 ] && echo finished mounting
else
    [ $debug -ne 0 ] && echo has mounted $mount_folder:/
fi


folders=()
files=()

for remote_path in ${remote_paths}; do
    [ $debug -ne 0 ] && echo remote_path: $remote_path
    local_path=$mount_dir/$mount_folder/$remote_path
    [ $debug -ne 0 ] && echo local_path: $local_path

    if [ -d $local_path ]; then
        [ $debug -ne 0 ] && echo local_path is dir
        folders+="$local_path"
    elif [ -f $local_path ]; then
        [ $debug -ne 0 ] && echo local_path is file
        files+="$local_path"
    else
        echo no such file or directory: $local_path
    fi
done

[ $debug -ne 0 ] && declare -p folders
[ $debug -ne 0 ] && declare -p files

# 用本地軟件打開棺聊,適用于mac伞租,windows用戶需修改下面代碼
if [ "$app" = "sub" ]; then
    # 你也可以修改代碼,換成你喜歡的文本編輯器
    open_with="/Applications/Sublime Text.app"
elif [ "$app" = "open" ]; then
    open_with=""
fi

if [ "$open_with" = "" ]; then
    for folder in $folders; do
        # folder=${folder/ /\\ }
        [ $debug -ne 0 ] && echo $folder
        open  $folder
    done
    if [ $#files -ne 0 ]; then
        open $files
    fi
else
    for folder in $folders; do
        # folder=${folder/ /\\ }
        [ $debug -ne 0 ] && echo $folder
        open -a $open_with $folder
    done
    if [ $#files -ne 0 ]; then
        open -a $open_with $files
    fi
fi

端口監(jiān)聽

編輯 ~/remote_open/remote_open_listen.sh

#!/bin/zsh

port=【本地nc端口】

this_dir_abs_path=$(cd "$(dirname "$0")"; pwd)

echo start nc
while read line; do
    echo "$line"
    zsh $this_dir_abs_path/remote_open.sh $line
done < <(nc -lk $port)
echo end nc

設(shè)置.ssh/config限佩,進(jìn)行端口轉(zhuǎn)發(fā)

為使服務(wù)器上nc發(fā)送消息到本地被監(jiān)聽到葵诈,ssh需將【遠(yuǎn)程nc端口】同【本地nc端口】轉(zhuǎn)發(fā)

Host 【hostname】
    HostName 【服務(wù)器的外網(wǎng)ip 或 url】
    User 【username】
    # 私鑰
    IdentityFile ~/.ssh/id_rsa
    PreferredAuthentications publickey
    # 用于remote open 的端口轉(zhuǎn)發(fā)
    RemoteForward 【遠(yuǎn)程nc端口】 localhost:【本地nc端口】
   # 其他設(shè)置...

其中

  • 【hostname】=服務(wù)器上執(zhí)行hostname的輸出
  • 【username】=服務(wù)器上執(zhí)行echo $USER的輸出
  • 【服務(wù)器的外網(wǎng)ip 或 url】=服務(wù)器上執(zhí)行curl ifconfig.me的輸出

設(shè)端口監(jiān)聽腳本為開機(jī)自啟

將端口監(jiān)聽腳本~/remote_open/remote_open_listen.sh設(shè)置為開機(jī)自啟、后臺(tái)運(yùn)行

mac用戶

操作教程詳見

  • 在 “自動(dòng)操作.app”中新建“應(yīng)用程序”祟同,
  • 在其中選中運(yùn)行shell腳本作喘,
  • 選擇使用zsh
  • 自動(dòng)操作腳本內(nèi)容寫
( ( 
zsh ~/remote_open/remote_open_listen.sh
) &) > /dev/null 2>&1
  • 保存到 ~/remote_open/remote_open.app

  • 系統(tǒng)偏好設(shè)置/用戶與群組/登錄項(xiàng),將~/remote_open/remote_open.app選中晕城,并勾選隱藏泞坦,設(shè)為開機(jī)啟動(dòng)項(xiàng)目。

windows用戶

請自行查找windows設(shè)置開機(jī)自動(dòng)運(yùn)行腳本的方法


本人原創(chuàng)砖顷,轉(zhuǎn)載請注明出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贰锁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子滤蝠,更是在濱河造成了極大的恐慌豌熄,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件物咳,死亡現(xiàn)場離奇詭異锣险,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門囱持,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夯接,“玉大人,你說我怎么就攤上這事纷妆】福” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵掩幢,是天一觀的道長逊拍。 經(jīng)常有香客問我,道長际邻,這世上最難降的妖魔是什么芯丧? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮世曾,結(jié)果婚禮上缨恒,老公的妹妹穿的比我還像新娘。我一直安慰自己轮听,他們只是感情好骗露,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著血巍,像睡著了一般萧锉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上述寡,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天柿隙,我揣著相機(jī)與錄音,去河邊找鬼鲫凶。 笑死禀崖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的螟炫。 我是一名探鬼主播波附,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼不恭!你這毒婦竟也來了叶雹?” 一聲冷哼從身側(cè)響起财饥,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤换吧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后钥星,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沾瓦,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贯莺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片风喇。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖缕探,靈堂內(nèi)的尸體忽然破棺而出魂莫,到底是詐尸還是另有隱情,我是刑警寧澤爹耗,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布耙考,位于F島的核電站,受9級特大地震影響潭兽,放射性物質(zhì)發(fā)生泄漏倦始。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一山卦、第九天 我趴在偏房一處隱蔽的房頂上張望鞋邑。 院中可真熱鬧,春花似錦账蓉、人聲如沸枚碗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽视译。三九已至,卻和暖如春归敬,著一層夾襖步出監(jiān)牢的瞬間酷含,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工汪茧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留椅亚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓舱污,卻偏偏與公主長得像呀舔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子扩灯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354