[小ネタ] リモートホストにSSH接続できることを確認してからのrsync + 日本語ポエム


リモートホストにSSH接続できることを確認してからrsyncする

リモートホストにSSH接続できることを確かめてからrsyncしたいなー、というそれだけのキッカケで書いたシェルスクリプト。恐らくシェルスクリプト初心者にも読みやすい作り、のはず。

単にrsyncする前にsshでログインして「:」だけ叩いて帰ってきて「どうだった?」と終了ステータスを捕まえて、sshが正常終了だったらrsyncする、というそれだけなんですが、終了ステータス捕まえるためだけに何秒も待たされるのが嫌だったので、sshコマンドのあとに「ConnectTimeout 1」オプションをつけています。

#!/bin/bash
LANG=C
set -eux

FROM_DIR=${HOME}/N/U/L/L/P/O/P/O/P/O
TO_DIR=${HOME}/M/A/R/I/N/A
SSH_USER=nullpopopo
TO_HOST=sakura

# ------------------------------------------------------------ #
# by @nullpopopo
# First Commit 2017/11/15
# ------------------------------------------------------------ #

SSH_TIMEOUT_STATUS=$(
     ssh -o "ConnectTimeout 1" ${TO_HOST} :     > \
     /dev/null 2>&1                             ; \
     echo $?
    )

if [ ${SSH_TIMEOUT_STATUS} = 0 ];
then
  ssh ${TO_HOST} mkdir -p ${TO_DIR}
  rsync -ahvz                           \
    ${FROM_DIR}/*                       \
    ${SSH_USER}@${TO_HOST}:${TO_DIR}/
fi

はい、答えだけ知りたい人はここで回れ右(つめたいなあ 偉そうだなあ)。

シェルスクリプト上達のキッカケを振り返ってみた

先ほどのシェルスクリプトもそうなんですけど、今ぼくが書いてるシェルスクリプトって、基礎的なことはほとんど全部、先ほど紹介した「入門UNIXシェルプログラミング」から学んだんですよね。もちろん最初は変数なんて使わない、ifすら使わない、行きっぱなしで戻ってこない直線番長でしたよ。

しかし、繰り返し実行していると、デバッグしたいじゃないですか。直線番長だとバグ見つけるのが大変じゃないですか。でもって、だいたいバグの原因って高尚なものではなくて

  • くだらないスペルミス
  • 前提条件が揃ってないのに実行しようとしてしまう

がほとんどだったんですね、私の場合。

しかも結構シェルスクリプトの深い行でバグがありそうだ、となった時は探すのが大変で、だったら頻出するディレクトリ名やファイル名は変数にしてしまおう、となったわけでして(PATHとかHOMEとかのシステム変数を上書きしようとしてバグったことは苦い思い出ですが、それはまた別のお話)。

で、後者の「前提条件が揃っていないのに実行しようとしてしまう」バグと一言で言い表すようになるまでには時間がかかりましたね。例えばそこにファイルがあることを前提にしたいなら

FILENAME=/path/to/hoge.txt
if [ -f ${FILENAME} ];
then
  cat ${FILENAME}
fi

というコードになるでしょうし、もっと慎重に書くなら「hoge.txt」のあるパスを決め打ちしないでディレクトリ名も変数にしてしまって、そもそもディレクトリがなければ警告を発して異常終了、ディレクトリがあれば先ほどのコードを実行する、というのも

DIRECTORY=/path/to
FILENAME=${DIRECTORY}/hoge.txt
if [ ! -d ${DIRECTORY} ];
then
  echo "${DIRECTORY} がありません!"
  exit 1
else
  if [ -f ${FILENAME} ];
  then
    cat ${FILENAME}
  fi
fi

こんな風にかけてしまうわけですよ。で、ifのネストなんてやだなあ、と思ったなら

DIRECTORY=/path/to
FILENAME=${DIRECTORY}/hoge.txt
if [ -d ${DIRECTORY} -a -f ${FILENAME} ];
then
  cat ${FILENAME}
else
  echo "${DIRECTORY} がありません!"
  exit 1
fi

ifをandの条件式にしたらスッキリしましたね。ネストがなくなって可読性が上がりました(そもそもディレクトリの存在確認とそのディレクトリ配下にあるファイルの存在確認は冗長ですが、あくまで例題なので)。


自分の考えを言語化しよう

で、ここまで来ると、シェルの文法なんてオマケでして、自分の母国語で正しく物事を認識できるか、こそが一番大事なわけなんですよ。

むかーし、ウサギィの町社長が

こう言ってまして、まったくその通りなんですね。ほんと、普段話す言葉が雑だとプログラムを書くのにえらい苦労するのですよ。


ハイコンテクスト文化の罠

それともう1つ、ある一定の年齢かつエンジニア属性じゃない人と日本語で会話していると、主語述語動詞名詞をかなり省いちゃうことができるんですね。接続詞すら省けちゃう。つまり、自分の認識と相手の認識に齟齬がないという前提あるいは「俺がこう思うんだからお前も察しろ」みたいな暗黙の主従関係が前提にあるからこそ成り立つコミュニケーションだと思うのですね。例えば

「おーいお茶」だけ言われたって、日本語を覚えたての人に同じこと言っても「私は茶じゃありません。けん(Kenneth)です」なんて返されるかも知れません。つまり、察するという文化は自分と相手が同じ文化、同じボキャブラリーを持って初めて成り立つものですが、コンピューターはそうもいきません。(だからこそプログラミング「言語」なのでしょう)

もう1つ、自立した大人たるもの、自分の考えや思想、相手への期待を明にせず言葉にしない、ということは非常に危険なのでは、ということ。先ほども例に挙げた「暗黙の主従関係」にも繋がるんですよね、これ。お互いが会話のキャッチボールをしているつもりで

「それではこの間のアレやってください」

なんていう会話、よくありがちじゃないですか。もう指示語の嵐で気が狂いそうなんですよ。大げさですが。で、大抵は勘違いして聞いた(行動の責任を持った)方が間違って怒られるわけじゃないですか。これ、ハイコンテクスト文化の欠点だと思うのですよ。

 日経ビジネスオンライン 
英語ができても、意思が通じるとは限らない コミュニケーションに欠かせない文化...
http://business.nikkeibp.co.jp/article/topics/20100921/216311/
「英語ができるから、コミュニケーションができる」という認識は間違いだと思う。語学からはじまり、文化的差異に気をつけてコミュニケーションする努力をしないと、非常に大きな過ちを犯す。

ハイコンテクスト文化とローコンテクスト文化の違いについては↑が詳しいのですが、エドワード・T・ホールの本あたりをちゃんと読んでみたいですね。

さて、なんでスクリプト1枚からこんなにポエってしまいましたが、まとめると

プログラム書くならまず自分の母国語で自分の考えを正しく言語化しよう

ということですね。あー長かった。