背景
リモートサーバにバイナリだけアップロードしてちょっとした動作確認を繰り返したいとき
local> compile-command source_code
local> scp built_binary remote-server:~/
local> ssh remote-server
remote> sudo cp built_binary /opt/app/
remote> execute-command built_binary
という感じで、いちいちsshしてcpして実行するのがめんどくさかったので、
ローカルのシェルから出ることなく全ての作業を行いなーと思いました。
「リモートサーバーにコマンドだけ投げつけてえ!」
環境
クライアントマシン: MacOS Catalina 10.15.4
リモートマシン: Amazon Linux2
やり方
めちゃ簡単でした。
ssh remote-server <command>
で行けるみたいです。
ssh remote-server ls
だとそのリモートサーバのログインユーザのホームディレクトリ一覧が出てきます。
sudoを使いたい
sudoを使うためには-tオプションを使いましょう。
ssh -t remote-server sudo cp ./file /opt/libs/
[sudo] password for hogehoge #ここでパスワード入力
パスワード入れるのもめんどいわ!
ssh remote-server 'echo password | sudo -S cp ./file /opt/libs'
として、2回目以降はhistoryから使い回しましょう。
historyにパスワードが見えてしまいますが、それは自己責任でw
おまけ:-tだけじゃダメなとき(4/29追記)
このようにパイプで繋がっている場合では-tだけでは以下のようなエラーが出ます。
ls *.kt | xargs -I {} ssh -t remote-server sudo cp ./{} /opt/libs
Pseudo-terminal will not be allocated because stdin is not a terminal.
sudo: no tty present and no askpass program specified
その場合は-tオプションを2回重ねましょう。
ls *.kt | xargs -I {} ssh -t -t remote-server sudo cp ./{} /opt/libs
そもそもssh -tオプションとは?
man ssh
...
-t Force pseudo-terminal allocation.
This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful,
e.g. when implementing menu services. Multiple -t options force tty allocation,
even if ssh has no local tty.
...
psedo-terminalとは疑似端末のこと。つまりsudoのパスワード入力を受け付けはこの疑似端末を介して行われます。
普通にsshでリモートサーバに入る時は自動で疑似端末が割当たります。そして我々は疑似端末上で操作していることになります。
ですが、このようにコマンドを投げつける場合は疑似端末は割りあたりません。
ところがsudoのパスワードは必要であるので疑似端末上でパスワードの入力を行う必要があります。
そこで-tオプションで強制的に疑似端末を割り当てることができます。
ここでさらに-t -tとすると疑似端末に加えttyを割り当てることができます。
間違いを恐れずに説明するならばttyとは標準入出力インターフェースみたいなもので、ローカルの端末(自PC)の入力はttyを介して疑似端末(リモートサーバ)に送られます。
ところがこのようにxargsを使用すると、プログラム(xargs)がsshを呼び出すことになります。
つまりPC操作者が入力したパスワードを受け取ってプログラム(xargs)自身が疑似端末へ代わりに入力することになります。
しかしプログラムはそのままでは標準入力するためのインターフェース(tty)を持っていないので入力できません(端末にはttyは付属しているので端末同士は特別意識する必要はない)。
そこで2個目の-tオプションにより、手動でttyを割り当てることで標準入力が可能となります。