
まとめてjpegにするワンライナーを書きました。
find . -mindepth 1 -name '*.HEIC' | xargs -I@ basename @ .HEIC | xargs -I@ sips --setProperty format jpeg @.HEIC --out @.jpg
gistの方にも置いておきます。
まとめてjpegにするワンライナーを書きました。
find . -mindepth 1 -name '*.HEIC' | xargs -I@ basename @ .HEIC | xargs -I@ sips --setProperty format jpeg @.HEIC --out @.jpg
gistの方にも置いておきます。
最近はラズベリーパイをつかってIoTデバイスを作ろうという試みをやっています。
ラズパイのキットはこれが調子いいです。
ラズベリーパイ、Linuxが搭載されていますし、無線LANの挙動も実に軽快なので、LAN内にいる時はSSH接続がとても簡単です。しかし、IoTデバイスというのは常にLAN内にあるものとも限らず、SIMカードを使ってスマホのように各キャリアが提供するネットワークを使ってインターネットにアクセスする必要もあります。
私はラズパイをインターネットに接続させるSIMとして、Soracomを選びました。
SoracomのSIMにはグローバルIPが割り振られておりません。
そしてIPが割り当てられていない以上、一般的なTCP/IP - DNSを使ったSSH接続はできないということになります。
とはいえ開発中、Docomoネットワークを使ってインターネットに接続するSIMを使ったラズパイに対して、SSH接続したいことは往々にしてよく起こります。
それができなければわざわざシーケンス制御のプログラムを書いて実行しなければならない、といったような。
ということで、SoracomのSIMをはじめとする、グローバルIPが割り振られていないSIMを使ってインターネットにアクセスをしているラズパイに対して、SSH接続をする方法(NAT超えSSH接続)をここに記しておきたいと思います。
使っているラズパイの条件は下記の通りです。
raspberry pi : Raspbian GNU/Linux 9.8 (stretch)
autossh : 1.4e
soracom sim : SORACOM Air SIM plan-D (SMS/data)
3G USBドングル : Abit AK-020
まずは中継サーバーを用意しましょう。
この方法は図のように、中継サーバーを介してラズパイにアクセスをすることになります。
上にも書きましたがSoracom SIMを使ったラズパイの場合、グローバルIPが割当てられていないことで、通常のTCP/IPだけでは座標を特定することができないからです。
なので、SSHポートフォワーディング(SSHトンネル)という技術を使って、中継サーバーを介してラズパイにアクセスできるようにします。
簡単に順番に仕組みを説明すると
ということです。
ポートフォワーディングというのは、SSH接続をする際に、接続先のサーバーの任意のポートと、接続元のデバイスの任意のポートに転送(同一化)させるというような技術です。
このケースの場合、(ラズパイのSSHポートは22番であるという前提とします)接続先の中継サーバーの4649番のポートを、接続元のラズパイの22番ポートに転送するということによって、中継サーバーにアクセスしたMacbookは中継サーバーの4649番ポートにssh接続をすることで、ラズパイに対してssh接続をするという仕組みを取ります。
前提として中継サーバーに接続する際に使うユーザーを中継サーバー側で用意しておく必要があります。
このケースの例としてuserを使いますので、中継サーバー側で作成しておいてください
# adduser user
この方法ではラズパイの起動直後に中継サーバーに対してSSH接続をしなければなりませんので、パスワードを入力することができません。そのため公開鍵暗号方式を使ってパスワードなしで接続できるようにします。
まずは、中継サーバー側のsshd_configのPubkeyAuthenticationはyesに設定しておきましょう。
次にラズパイ側でssh接続のための鍵を作ります。
ssh-keygen -t rsa
(鍵の暗号化方式はどれがよいかという議論はありますが、ここでは省略、今回はrsaを採用します。)
あとは対話形式で鍵の作成が進んでいきますが、パスフレーズを聞かれるところでは何も入力せずに進んでください。
+---[RSA 2048]----+ | .. . ... | | ... o . | | o. + * o | | . .. o & o| | S = O | | ..+ o| | ..oooEo| | o*==+*| | .*@BO=| +----[SHA256]-----+
こういう暗号のイメージが表示されたら鍵の作成は完了です。
~/.ssh/に
id_rsa
id_rsa.pub
の2つのファイルが生成されています。
id_rsaが秘密鍵、id_rsa.pubが公開鍵です。
秘密鍵は絶対に人の手に渡らないように、ネットワークに流れることのないようにしましょう。
出来上がった公開鍵を中継サーバーに送り、鍵を認証してもらいます。
ssh-copy-id user@192.168.0.100 #sshdのlistenポート番号を変更している場合は下記のように ssh-copy-id user@192.168.2.30 -o port=10000
userと@以降のipについてはssh接続するユーザー名と接続先のホスト名またはIPアドレスを入力します。
コマンドが通ればパスワードを尋ねられますので、中継サーバー上でuserに設定しているパスワードを入力しましょう。公開鍵の転送が完了します。
この状態で
ssh user@192.168.0.100
と入力して、パスワードを聞かれずにサーバーにログインできれば成功です。
ラズパイから中継サーバーにログインする時に使うコマンドに、ポートフォワーディング用のオプションを追記します。
ssh -R 4649:localhost:22 user@192.168.0.100
-R 4649:localhost:22
というオプションを追加することで、中継サーバーの4649番ポートをラズパイの22番ポートに転送できます。
したがって上図に示しているMacbookは、中継サーバーにログインした後
ssh pi@localhost -o port=4649
とすることで、中継サーバーを経てラズパイにログインすることが可能になりました。
ラズパイの起動直後に中継サーバーへssh接続を自動化するには、ラズパイのcrontabに追記するのが良いのではないかと思います。
crontab -e
によってcrontabを開き、
@reboot ssh user@192.168.0.100
と書き込めば起動時に自動的に中継サーバーに接続しに行くようになります。
このとき、いくつかの設定を追加するのも良いかと思います。
具体的には ~/.ssh/config に下記のような設定を追加しておきます。
Host RelayServer HostName relay-server.com #中継サーバーのホスト名 User user IdentityFile ~/.ssh/id_rsa StrictHostKeyChecking no UserKnownHostsFile /dev/null ServerAliveInterval 60 ServerAliveCountMax 3 ExitOnForwardFailure yes RemoteForward 4649 localhost:22
それぞれのオプションの説明をします。
HostNameは中継サーバーのアドレスです。
Userには中継サーバーにログインするユーザー名を入力します。
IdentityFileは秘密鍵の場所を書きます。
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
によって、はじめて接続するホストの場合でも警告(fingerprint云々)を出さないようにしたり、known_hostsファイルに影響を与えることなく接続できます。
ServerAliveInterval 60
ServerAliveCountMax 3
このオプションによって、サーバーからのタイムアウトを回避します。
60秒毎にサーバーにメッセージを送り、ServerAliveCountMax の設定回数、3回まで繰りかえします。
もしサーバーが応答しなくなったら 180秒後に接続が切断されるようになるということですね。
ExitOnForwardFailure yes
このオプションによって、既にポートフォワード先のポートが空いてなかった場合はssh接続をせずに終了します。
RemoteForward 4649 localhost:22
このオプションで接続先の中継サーバーの4649番ポートに、接続元のラズパイの22番ポートに転送できます。
これらの設定が終われば、
ssh RelayServer
と入力するだけで上記で設定したオプションを踏まえたssh接続ができます。
自動で接続する際には -N -f オプションをつけてもいいです。それぞれ
-N は接続先でポートフォワーディングのみに利用する接続であることを明示するオプション
-f はバックグラウンドで実行することを明示するオプションです。
crontabの方にも
@reboot ssh -N -f RelayServer
と書いておくとこれらが自動で実行されます。
さらにautosshを使ってssh接続するという選択もあります。
普通のsshを使っても問題はないのですが、autosshの場合、セッションが何らかの原因で途切れてしまった場合、自動的に再接続をしてくれます。
autosshはsshと互換のあるコマンドですので、普段からautosshを使うのもありですね。
#apt-get install autossh
でインストールできます。
上記のことをautosshでやる場合、crontabには
@reboot autossh -M 0 -N -f RelayServer
と書きましょう。
-M 0 オプションは
autossh標準のsshコネクションモニタリングを無効にし、OpenSsh自体のモニタリングを有効にします。
OpenSsh自体のモニタリングとはServerAliveInterval 60や、ServerAliveCountMax 3などの設定のことです。
autosshのmanページで、これは推奨されています。
以上のことを実行すると、ラズパイ起動時に中継サーバーに自動で接続しにいき、そのセッションを使ってクライアント(macbook)からラズパイに接続しにいくことができるようになります。
しかし、ラズパイを再起動などすると、再接続までにとても時間がかかったりします(時間測ったら10分くらいかかりました)
その場合、中継サーバーをリブートしてから、ラズパイをリブートすると、すぐに接続できたりするのですが…
おそらく、ラズパイリブートする前にautosshの接続をきちんと切ってからリブートすればいいのかなあなんて今書きながら思いましたが、まだ試していません。
いずれにしろ、この方法を使ったSSH接続はあくまで開発途中での実験やデバッグに用いるのがよさそうです。
中継サーバー上のポートListenの履歴を、ラズパイが沈黙した後にすぐに削除するなどの施策を取ることができれば完全に安定させることができるのかも知れませんが。
なお、この記事を書くにあたって下記のサイトを参考にさせていただきました。
ありがとうございます。
SSH公開鍵認証でパスワード無しでログインする!ユーザも指定できる! | ぴぐろぐ
Soracom Airで繋がったデバイスにリモートからSSHする | DevelopersIO
ターミナルの、あるディレクトリの中で同じ接頭辞のならんだファイル群をvimで編集しようとするとき、ターミナルの予測(タブキー)を叩きまくるのが面倒です。
具体的にはこんな状態
_hoge_hoge
_hoge_fuga
_hoge_piyo
_hoge_piyo_hage
この場合、タブを押す回数は2〜3度でよいのですが、もっと名前が重複する場合もあるし、そういったファイルに何度もアクセスする場合、面倒になります。
特に括弧とかスペースを含むファイル名を選ぶのは面倒くさくてしょうがねえっていう。
(まあvim内部のヒストリー使ったりとか、シェルのヒストリー使ったりしたらって話にもなるかと思いますが、それはおいといて)
ということで、フィルタリングソフトウェアのfzyによってインクリメンタルサーチを使って開きたいファイルを指定する方法を思いついたところ、かなり使い勝手が良かったのでお知らせします。
これはenhancdを使ってるといに思いつきました。
GitHub - b4b4r07/enhancd: A next-generation cd command with an interactive filter
まず、fzyをインストールします。
GitHub - jhawthorn/fzy: A better fuzzy finder
あとは
vi `ls | fzy`
とするだけで、その階層のファイル群がリストされるので、そのままタイプするとインクリメンタルサーチが出来て、選択したものが自動的にvimに渡されます。
.zshrc(.bashrc)には
alias vi='vim `ls | fzy`'
と書いておけばviと入力するだけでfzyを使ったファイルの選択画面に入ることができます。
こんな感じ
mvとかcpとかのファイル操作系のコマンドも、全部フィルタリングを使って実行できるようになるといいのになーと思うんだけど、対話的になると意味がない(面倒くさい)し…
と思いつつ作ってみた
#!/bin/bash file=$(ls | fzy) read -p "destination?:" dest cp $file $dest
動くけど使える気がしない
ってなるとせいぜいこんな感じか
cp `ls | fzy` dest
※dest:保存場所
まあ括弧とかスペースとか混ざった日本語ファイルに対しては有効そうな。
と思ってスペース付きのファイルでやってみたら、ファイルネームのスペースがデリミタと認識されて動きませんでした。IFSでデリミタを変更してもいいのかも知れませんが、ちょっとそれはどうかと
色々試した結果、一旦ファイル名を変数に保存してやれば動きました
file=$(ls | fzy);echo $file | xargs -I@ cp @ dest
なんだこれっていうw
追記
このことを
dyama's pageの管理人のdyama氏に話したところ
こういうのどうかなってことで下記のスクリプトをご提案いただきました。
$ cp "$(ls | fzy)" $(cat)
このスクリプトを実行すると、最初にカレントディレクトリのリストを選択画面に入って、その後入力待ちの状態のときに新しく設定するファイル名を入力してC-d(ctrl+d)で抜けるとそのファイル名でコピーがなされます。
catの標準入力をそのまま標準出力とする機能を用いて実現している方法なので、ディレクトリの予測補完などが使えないのが玉にキズであるとはいえ、十分にシンプルで使えそうなものになりました。ありがとうdyama氏。
これをcpe(cp-extended)コマンドとかで登録しとくと、便利なときもあるかも知れないね!