ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

AtomのRemote-FTPを使ってラズパイのファイル操作をする

今までWin-SCPを使ってサクラエディタでファイル操作していたのですが、常々できることならAtomを使いたいと思っていました(サクラエディタは好きですが、フォルダの階層を行き来しながらファイル操作するのが大変)。どうやらAtomを使ってリモートでファイル操作をするパッケージがあるようなので、それを使ってみます。

Remote-FTPAtomにインストールする

File > Settings > Install から、Remote-FTPをインストールします。

ローカルにプロジェクトファイルを作る

File > Open Folder から、適当なフォルダを開きます
例えば私の場合、ラズパイのprojectAというフォルダをリモート操作したいので、適当にローカルの"C:\Users\hoge\workspace\projectA"というフォルダを作成し、そのフォルダを開きました。

ftpconfigの設定

Packages > Remote-FTP > Create SFTP config file
すると.ftpconfigというファイルが開くので、それを編集します。

"protocol":"sftp"
"host":"ラズパイのIPアドレス"
"port":"SSHのポート番号(デフォルト22番)"
"user":"ラズパイにログインするときのユーザ名"
"pass":"ラズパイにログインするときのパスワード"
"remote":"ラズパイの開きたいディレクトリを絶対パスで指定"

他はデフォルトでいいと思います。

例えば私の場合、

"protocol":"sftp"
"host":"192.168.10.131"
"port":"49999"
"user":"pi"
"pass":"raspberry"
"remote":"/home/pi/projects/projectA/"

みたいにしました。

編集したら保存します。

ラズパイに接続する

Packages > Remote-FTP > Connect をクリックすると、接続を試みます。接続できたら「Connected」みたいなメッセージが出るはずです。
Connectedできてもラズパイのディレクトリ構造が表示されない場合、Packages > Remote-FTP > Toggleをクリックします。

ファイルを操作する

おそらく2つのトグル画面が表示されていると思いますが、
・左側がリモート(ラズパイ側)のフォルダ「/」
・右側がローカル(PC側)のフォルダ「Project」
になります。
リモート側のファイルをダブルクリックするとローカル側にファイルがダウンロード(コピー)されます。
リモート側のファイル(フォルダ)を右クリック > Downloadでも同じことができます。
ローカル側のファイルを自由に編集した後、保存すると自動でリモート側にアップロードされるようです。

すぐタイムアウトしてしまう

デフォルトではちょっとほっておいたらすぐタイムアウトしてリモートと接続を切ります。これが嫌な場合"connTimeout"や"keepalive"の値をいじれば良さそうです。ですが、リモートとの接続が切れている状態でも、ローカルのファイルを保存すると自動で接続・アップロードまでしてくれるので、別に気にしなくてもいい気がします。

これでAtom一つでフォルダ階層を行き来しながらファイル編集できます。すごく便利。Atomは神。ちょくちょくエラー出たり重かったりするけど。

Atomで"や'の補完機能を無効にする

Atom(というか多くのリッチなエディタ)では、「"」と打つと自動で「""」と補完してくれる。補完して...くれる...?補完しないでください。

http://hakomof.hatenablog.com/entry/2015/05/07/210328
上記サイトに方法が書いてあります。

File > Config をクリックすると、config.csonファイルが開きます。
そこに「"bracket-matcher": autocompleteBrackets: false」を追加することで無効にできます。

"*":
    "atom-ctags":{}
    "autocomplete-plus": {}
    ...
    (略)
    ...
    "bracket-matcher":
        autocompleteBrackets: false

あらゆるエディタ・ IDE についてるけど邪魔だと思ったことこそあれ、便利だと思ったことはない。無効。

完全に同意。

packet_write_wait: Connection to "IPアドレス": Connection reset by peer

SSHでラズパイに接続中、頻繁にぶつぶつ接続が切れる問題に遭遇。
接続が切れるときに、次のようなエラーメッセージが表示されました。

packet_write_wait: Connection to 192.168.8.132: Connection reset by peer

色々調べた結果、IPアドレスの衝突が原因でした。
ラズパイを固定IPアドレスで運用していると、別のDHCPで運用している端末にIPアドレスを奪われてしまう現象が起きていました。
DHCPでのIPアドレスの分配はホスト部が小さい数字から割り当てられるようになっていることが多いので、固定IPアドレスホスト部はなるべく大きい数字にしましょう。

Pythonで親ディレクトリのファイルをインポート

実行スクリプトの親ディレクトリのファイルをインポートする - Pythonで遊ぶよ - pythonグループ

長年これを探していました…!

hoge.py
└tests/
  └test_hoge.py

test_hoge.pyからhoge.pyをインポートします。

test_hoge.py

import os
import sys
sys.path.append(os.pardir)
import hoge

systemdのサービスの起動順序を決める

hoge1.serviceとhoge2.serviceという2つのサービスを作成しました。
「hoge1.seriveのExecStartで指定したスクリプトが完全に終了してからhoge2.serviceを起動する」ということをしたい場合は、サービスの起動順序を記述する必要があります。

[Unit]セクションにAfterとBeforeを記述すれば起動順序を指定できますが、これだけだと意図した順序で起動してくれませんでした。
原因は起動完了判定のタイミングで、[Service]セクションのTypeも考える必要があります。

Type = simpleは、「サービス起動と同時に起動完了と判定する」
Type = oneshotは、「サービス起動して、ExecStartで指定したスクリプトが終了したら起動完了と判定する」
Systemd入門(4) - serviceタイプUnitの設定ファイル - めもめも


なので、今回のような場合はhoge1.serviceをType = oneshotにする必要があります。

hoge1.service

[Unit]
Description = hoge1.sh runs before hoge2.sh
Wants = multi-user.target
Before = hoge2.service

[Service]
ExecStart = /home/pi/hoge1.sh
Restart = no
Type = oneshot

[Install]
WantedBy = multi-user.target

hoge2.service

[Unit]
Description = hoge2.sh runs after hoge1.sh
After = hoge1.service

[Service]
ExecStart = /home/pi/hoge2.sh
Restart = no
Type = simple

[Install]
WantedBy = multi-user.target

実際に意図した順序で起動しているかを確認してみます。
Systemdのサービスの依存関係を調べる方法 - ククログ(2015-12-28)

$ systemd-analyze plot > systemd.svg

作成されたsystemd.svgファイルを適当なブラウザにドラッグ&ドロップすると、デーモンの起動順序を確認できます。
f:id:takeg:20170215220336p:plain
hoge1.serviceの後にhoge2.serviceがactiveしていることがわかります。
どうやらこれで良さそうです:)

anaconda4.3.0でfcntlのflock()が使えない

・Ubuntu14.04 LTS
・pyenvを使ってAnaconda4.3.0 (python3.6.0)をインストール
で、fcntlモジュールのflock()等が使用できません。
" AttributeError: module 'fcntl'has no attribute "エラーが起きます。

$ python
Python 3.6.0 |Anaconda 4.3.0 (32-bit)| (default, Dec 23 2016, 12:22:10) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import fcntl
>>> fcntl.LOCK_EX
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'fcntl' has no attribute 'LOCK_EX'
>>> 

なぜ?
調べると、同じディストリビューションで困っている人を発見しました。
Python 3.6になったAnaconda 4.3.0をインストールしてはまった - Qiita

下のChangelogにあるようにいくつかパッケージが外されている。どのパッケージが該当するのかはっきりしないが、いくつか機能がなくなっている。

パッケージが外されている……いやしかし、標準ライブラリのモジュールを外すことってありえるのかな?と疑問。もしかしたらこの人とは関係ないかも?

Anaconda4.3.0のChangelogを眺めてみました。
Anaconda changelog | Continuum Analytics: Documentation

Removed (from installer only):

anaconda-clean
dynd-python
filelock <==
libdynd
nb_anacondacloud
nb_conda
nb_conda_kernels
nbpresent
patchelf
pkginfo

filelock...?うーん……。

ちなみに、システムにプリインストールされているpython2.7.6とpython3.4.3だと普通に使用できます。

$ python2
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import fcntl
>>> fcntl.LOCK_EX
2
>>> 
$ /usr/bin/python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import fcntl
>>> fcntl.LOCK_EX
2
>>> 

systemdの"code=exited, status=203/EXEC"エラー

root@raspberrypi:~# systemctl status mydaemon.service       -l
● mydaemon.service - This is my daemon
Loaded: loaded (/etc/systemd/system/mydaemon.service; enabled)
Active: failed (Result: exit-code) since 木 2017-02-09 17:01:27 JST; 1s ago    
Process: 1587 ExecStart=/root/hoge_task/hoge_task.sh (code=exited, status=203/EXEC)                          
Main PID: 1587 (code=exited, status=203/EXEC)
209 17:01:27 raspberrypi systemd[1]: Started This is my daemon.
209 17:01:27 raspberrypi systemd[1]: mydaemon.service: main process exited, code=exited, status=203/EXEC                                
209 17:01:27 raspberrypi systemd[1]: Unit mydaemon.service entered failed state.

systemctl statusを見てもエラーの原因はわかりません。こういうときはsyslogを見ます。

$ less /var/log/syslog
()
Feb  9 14:20:57 raspberrypi systemd[416]: Failed at step EXEC spawning /root/hoge_task/hoge_task.py: Permission denied

Permission denied...権限がないと言われています。
確認してみるとhoge_task.shの権限は644でした。実行権限を与えます。

$ chmod 744 /root/hoge_task/hoge_task.sh

再度チャレンジ。

$ systemctl start mydaemon
$ systemctl status mydaemon
● mydaemon.service - This is my daemon.
   Loaded: loaded (/etc/systemd/system/mydaemon.service; enabled)
   Active: active (running) since 木 2017-02-09 17:07:56 JST; 7min ago
 Main PID: 416 (hoge_task)

成功しました。
デーモンのエラーはとりあえずsyslogを見ましょうという教訓でした。