hotch-potch, Note to self

いろいろ作業記録

RaspberryPi上のPython3でSQLServerに読み書き

はじめに

Raspbian上で動かすPython3のスクリプトから、別のサーバのSQLServerに対しデータを書き込む方法について。(Python2.7と違って、apt-getでpymssqlのパッケージが入れられなかったので、そのインストール手順の覚え書きです)

環境

  • Raspbian(2018-11-13-raspbian-stretch-lite)
  • Python3

SQLServer用のライブラリ「pymssql」をインストール

pipを使用するので、インストールしていなければ下記を実行

$ sudo apt-get install python3-pip

pymssqlのコンパイルに必要なライブラリをインストール

$ sudo apt-get install freetds-dev -y
(補足)FreeTDS-devを入れ忘れると・・・

コンパイル中に下記のエラーが出ます

...
    creating build/temp.linux-armv6l-3.5/src
    arm-linux-gnueabihf-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fdebug-prefix-map=/build/python3.5-6waWnr/python3.5-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/include -I/usr/include/python3.5m -c src/_mssql.c -o build/temp.linux-armv6l-3.5/src/_mssql.o -DMSDBLIB
    src/_mssql.c:594:22: fatal error: sqlfront.h: No such file or directory
     #include "sqlfront.h"
                          ^
    compilation terminated.
    error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1

    ----------------------------------------
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-zgxb1qiz/pymssql/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-_78s2jjv-record/install-record.txt --single-version-externally-managed --compile --user --prefix=" failed with error code 1 in /tmp/pip-build-zgxb1qiz/pymssql/

pipからpymssqlをインストール

インストールを完了するのに、RaspberryPi3で15分程度、RaspberryPiZeroWで1時間弱掛かります。

$ pip3 install pymssql
Collecting pymssql
  Downloading https://files.pythonhosted.org/packages/2e/81/99562b93d75f3fc5956fa65decfb35b38a4ee97cf93c1d0d3cb799fffb99/pymssql-2.1.4.tar.gz (691kB)
    100% |????????????????????????????????| 696kB 97kB/s
Building wheels for collected packages: pymssql
  Running setup.py bdist_wheel for pymssql ... done
  Stored in directory: /home/pi/.cache/pip/wheels/21/35/92/911576b44bbe7c19ff65d0f90a4af9a9571db4af36ffd3ede1
Successfully built pymssql
Installing collected packages: pymssql
Successfully installed pymssql-2.1.4

pymssqlの動作チェック

テーブルにレコードをf追加する簡単なスクリプトでテストします。

SqlServerのテーブルを作成

create table T_LogTest(
	DateAppend datetime,
	ClientID NVARCHAR(255),
	Value0 smallint,
	Value1 smallint,
	Value2 smallint);

書き込みスクリプト

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from os import getenv
import pymssql

conn = pymssql.connect('<host name>', '<database name>', '<user name>', '<password>')
cursor = conn.cursor()

cursor.execute("""
    INSERT INTO T_LogTest (
        DateAppend ,
        ClientID ,
        Value0 ,
        Value1 ,
        Value2)
    VALUES (
        GETDATE(),
        'hoge',
        2000,
        2010,
        2020)
    """)

conn.commit()

conn.close()

JETSONの"apt-get update"エラー

はじめに

久しぶり(18年10月以来ぶり)にJETSONを起動して、Ubuntuのアップデートをしようと思ったら、エラーが出てしまいました。
そのときの処置のメモです。

症状

nvidia@tegra-ubuntu:~$ sudo apt-get update
...
GPG error: file:/var/cuda-repo-9-0-local  Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F60F4B3D7FA2AF80
...

処置

こちらを参考にしました。
https://devtalk.nvidia.com/default/topic/1030999/jetson-tx2/fresh-install-of-the-new-jetpack-with-errors/

キーの登録をし直す必要があるみたいです。

nvidia@tegra-ubuntu:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F60F4B3D7FA2AF80
nvidia@tegra-ubuntu:~$ sudo apt-get update
nvidia@tegra-ubuntu:~$ sudo apt-get upgrade -y
nvidia@tegra-ubuntu:~$ sudo apt-get autoremove
nvidia@tegra-ubuntu:~$ sync
nvidia@tegra-ubuntu:~$ sudo reboot
...
nvidia@tegra-ubuntu:~$ uname -a
Linux tegra-ubuntu 4.4.38-tegra #1 SMP PREEMPT Thu Mar 1 20:49:20 PST 2018 aarch64 aarch64 aarch64 GNU/Linux

RaspberryPiにROSを簡単に入れてみる

はじめに

Raspbian(2018-11-13-raspbian-stretch)のROSパッケージをそのままインストールしてみました。
古いバージョンを使うことになるので、実際の所、良いのか分かりませんが、ひとまず手順を残します。

ROSの入門は、こちらを教科書にさせて頂きました。
ROS講座00 目次 - Qiita

下調べ

apt-cache で、RaspbianのROSのバージョンを調べてみました。
だいぶ古いバージョン(2016年春頃のリリース)のようです。

~ $ apt-cache show ros-core
Package: ros-core
Source: ros-metapackages
Version: 1.7
Installed-Size: 8
Maintainer: Debian Science Maintainers <debian-science-maintainers@lists.alioth.debian.org>
Architecture: all
Depends: python-rosclean, python-rosbag, python-rosgraph, python-roslaunch, python-rosmaster, python-rosmsg, python-rosnode, python-rosparam, python-rosservice, python-rostopic, python-message-filters, python-roswtf, rosout, topic-tools
Recommends: rosbash
Size: 2380
SHA256: e256a50ff7da3fb0c7ba72b73d2caeb5a26106fd5da2e73668f49525c08729b1
SHA1: 894bb519f4775444c2282053a13ce3ec2e5737e5
MD5sum: e7e6afb83388f46e2f52cf06672bacd3
Description: Robot OS core metapackage
 This package is part of Robot OS (ROS). It is a metapackage
 providing all the ROS core system.
 .
 Different to upstream, this packages does not provide geneus and
 rosbag_migration_rule.
 Please install them from source, if you need them.
Description-md5: 4b79f51f56b69a7611fb956936b6da3c
Section: metapackages
Priority: extra
Filename: pool/main/r/ros-metapackages/ros-core_1.7_all.deb

インストール

”desktop-full-dev”というパッケージで、一通り必要な機能が入ります。
こちらを参考にしています。
ROS講座02 インストール - Qiita

pi@raspi3:~ $ sudo apt-get install ros-desktop-full-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  autoconf automake autopoint autotools-dev bzip2-doc bzr catkin cl-actionlib cl-actionlib-msgs cl-bond
...
  x11proto-scrnsaver-dev x11proto-xext-dev x11proto-xf86vidmode-dev x11proto-xinerama-dev xorg-sgml-doctools
  xtrans-dev
0 upgraded, 863 newly installed, 0 to remove and 1 not upgraded.
Need to get 323 MB of archives.
After this operation, 1520 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
...

インストール前後のディスク使用量

インストール前
pi@raspi3:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  9.9G  4.0G  72% /
インストール後
pi@raspi3:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G   12G  2.2G  85% /

ROSの初期化

pi@raspi3:~ $ sudo rosdep init
Wrote /etc/ros/rosdep/sources.list.d/20-default.list
Recommended: please run

        rosdep update

pi@raspi3:~ $ rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml
Query rosdistro index https://raw.githubusercontent.com/ros/rosdistro/master/index.yaml
Add distro "ardent"
Add distro "bouncy"
Add distro "crystal"
Add distro "groovy"
Add distro "hydro"
Add distro "indigo"
Add distro "jade"
Add distro "kinetic"
Add distro "lunar"
Add distro "melodic"
updated cache in /home/pi/.ros/rosdep/sources.cache

catkinの準備

pi@raspi3:~ $ mkdir -p ~/catkin_ws/src
pi@raspi3:~ $ cd ~/catkin_ws/src
pi@raspi3:~/catkin_ws/src $ catkin_init_workspace
Creating symlink "/home/pi/catkin_ws/src/CMakeLists.txt" pointing to "/usr/share/catkin/cmake/toplevel.cmake"
pi@raspi3:~/catkin_ws/src $ ls -la
total 8
drwxr-xr-x 2 pi pi 4096 Feb  6 17:34 .
drwxr-xr-x 3 pi pi 4096 Feb  6 17:34 ..
lrwxrwxrwx 1 pi pi   38 Feb  6 17:34 CMakeLists.txt -> /usr/share/catkin/cmake/toplevel.cmake
pi@raspi3:~/catkin_ws/src $ cd ~/catkin_ws
pi@raspi3:~/catkin_ws $ catkin_make
Base path: /home/pi/catkin_ws
Source space: /home/pi/catkin_ws/src
Build space: /home/pi/catkin_ws/build
Devel space: /home/pi/catkin_ws/devel
Install space: /home/pi/catkin_ws/install
####
#### Running command: "cmake /home/pi/catkin_ws/src -DCATKIN_DEVEL_PREFIX=/home/pi/catkin_ws/devel -DCMAKE_INSTALL_PREFIX=/home/pi/catkin_ws/install -G Unix Makefiles" in "/home/pi/catkin_ws/build"
####
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Using CATKIN_DEVEL_PREFIX: /home/pi/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH:
-- Found PythonInterp: /usr/bin/python (found version "2.7.13")
-- Using PYTHON_EXECUTABLE: /usr/bin/python
-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /home/pi/catkin_ws/build/test_results
-- Found gtest sources under '/usr/src/gtest': gtests will be built
-- nosetests not found, Python tests can not be run (try installing package 'python-nose')
-- catkin 0.7.4
-- BUILD_SHARED_LIBS is on
-- Configuring done
-- Generating done
-- Build files have been written to: /home/pi/catkin_ws/build
####
#### Running command: "make -j4 -l4" in "/home/pi/catkin_ws/build"
####

ROSのサンプルプログラムを試してみる

こちらを参考にします。
ROS講座03 Pub &amp; Sub 通信 - Qiita

コンパイルまで終わらせます。

pi@raspi3:~/catkin_ws $ catkin_make
Base path: /home/pi/catkin_ws
Source space: /home/pi/catkin_ws/src
Build space: /home/pi/catkin_ws/build
Devel space: /home/pi/catkin_ws/devel
Install space: /home/pi/catkin_ws/install
####
#### Running command: "make cmake_check_build_system" in "/home/pi/catkin_ws/build"
####
####
#### Running command: "make -j4 -l4" in "/home/pi/catkin_ws/build"
####
[100%] Built target basic_simple_talker
[100%] Built target basic_simple_listener

ターミナル1つ目:roscoreを動かします

pi@raspi3:~/catkin_ws $ source ~/catkin_ws/devel/setup.bash
pi@raspi3:~/catkin_ws $ roscore
... logging to /home/pi/.ros/log/2ab1e868-29f0-11e9-8b33-b827ebaf3240/roslaunch-raspi3-1072.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://raspi3:41255/
ros_comm version 1.12.6


SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.6

NODES

auto-starting new master
process[master]: started with pid [1082]
ROS_MASTER_URI=http://raspi3:11311/

setting /run_id to 2ab1e868-29f0-11e9-8b33-b827ebaf3240
process[rosout-1]: started with pid [1095]
started core service [/rosout]

ターミナル2つ目:talkerを動かします

pi@raspi3:~/catkin_ws $ source ~/catkin_ws/devel/setup.bash
pi@raspi3:~ $ rosrun basic_lecture basic_simple_talker
[ INFO] [1549445114.110764374]: hello world!
[ INFO] [1549445114.210512172]: hello world!
...

ターミナル3つ目:listenerを動かします

pi@raspi3:~/catkin_ws $ source ~/catkin_ws/devel/setup.bash
pi@raspi3:~ $ rosrun basic_lecture basic_simple_listener
[ INFO] [1549445114.412048604]: I heard: [hello world!]
[ INFO] [1549445114.511398797]: I heard: [hello world!]
...

talkerの方のターミナルで、プログラムを止めるとメッセージが止まり、プログラムを動かすとメッセージが流れます。
ターミナルを開くたびに、毎回

source ~/catkin_ws/devel/setup.bash

を入力していますが、教科書の通り、.bashrcに追記した方が良いですね。

(覚え)roscoreを動かし忘れたとき

このようなエラーメッセージが出ます。

ターミナル2つ目:talker
pi@raspi3:~ $ rosrun basic_lecture basic_simple_talker
[ERROR] [1549445150.003231955]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...
^Cpi@raspi3:~ $
ターミナル3つ目:listener
pi@raspi3:~ $ rosrun basic_lecture basic_simple_listener
[ERROR] [1549445154.933464174]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...
^Cpi@raspi3:~ $

systemdに自作スクリプトを登録

概要

自作のスクリプトをRaspbian上のsystemdの管理下に置いて、デーモンとして使う方法です。

起動スクリプトの準備

自作のスクリプトを呼び出す起動スクリプトを作成します。 ここでは「/home/pi/myservice」というディレクトリに、「daemon.sh」と言う名前のスクリプトを作ります。 そこから、同じディレクトリにある自作のスクリプト「main.py」を呼び出すこととします。

$ cd /home/pi/myservice
$ touch daemon.sh
$ chmod 755 daemon.sh
  • daemon.sh ここでは、main.pyの標準出力とエラー出力は、myservice.logにリダイレクトして書き出すようにしています。 出力を省略すると、journaldの方に出力されます。必要に応じて選択します。
#!/bin/bash

SCRIPTDIR=/home/pi/myservice
LOGDIR=$SCRIPTDIR/log

exec /usr/bin/env /usr/bin/python3 $SCRIPTDIR/main.py >> $LOGDIR/myservice.log 2>&1

systemdの*.serviceファイルの作成

systemdの管理下に入れるための、個別の設定ファイルを作ります。 「/home/pi/myservice」フォルダのなかに、「myservice.service」を作成します。

$ touch myservice.service

「myservice.service」の内容

[Unit]
Description=This is My Service
After=local-fs.target
ConditionPathExists=/home/pi/myservice

[Service]
ExecStart=/home/pi/myservice/daemon.sh
ExecStop=/bin/kill ${MAINPID}
Restart=on-failure
StartLimitInterval=60
StartLimitBurst=3
KillMode=mixed
Type=simple
User=pi
Group=pi

[Install]
WantedBy=multi-user.target
項目 設定内容
Description このデーモンの概要を説明する文章
After=local-fs.target ファイルシステムが有効になってから起動
ConditionPathExists=/home/pi/myservice このフォルダが有れば起動する
ExecStart=/home/pi/myservice/daemon.sh 起動の対象となる実行ファイル
ExecStop=/bin/kill ${MAINPID} 停止時に発行するコマンド
Restart=on-failure 0以外の終了コードで停止したら再起動
StartLimitInterval=60 , StartLimitBurst=3 StartLimitIntervalの時間の間にStartLimiBurst回以上の再起動があったら、次のStartLimitIntervalの時間の間は再起動を取りやめ
KillMode=mixed メインプロセスはSIGTERM/SIGKILLで停止。続けてグループ内の全ての残プロセスをSIGKILLで停止
Type=simple 起動の対象となる実行ファイルが実行したらすぐに起動完了みなす。(フォアグラウンドで実行を継続するスクリプト
User=pi , Group=pi ユーザ/グループ pi として実行する
WantedBy=multi-user.target 起動設定するランレベルの指定:コンソールログインマルチユーザモード

systemdのフォルダに、.serviceファイルを置く。

シンボリックリンクでOK。

$ sudo ln -s $PWD/myservice.service /etc/systemd/system

設定の再読込

$ sudo systemctl daemon-reload

設定の確認

$ sudo systemctl list-unit-files --type=service
UNIT FILE                              STATE
alsa-restore.service                   static
...(省略)
myservice.service               linked
...(省略)

$ sudo systemctl status myservice.service
● myservice.service - This is My Service
   Loaded: loaded (/home/pi/myservice/myservice.service; linked; vendor preset: enabled)
   Active: inactive (dead)

有効化する

$ sudo systemctl enable myservice.service
Created symlink /etc/systemd/system/multi-user.target.wants/myservice.service → /home/pi/myservice/myservice.service.

起動する

$ sudo systemctl start myservice.service
$ sudo systemctl status myservice.service
● myservice.service - This is My Service
   Loaded: loaded (/home/pi/myservice/myservice.service; linked; vendor preset: enabled)
   Active: active (running) since Mon 2019-01-07 13:48:35 JST; 2s ago
 Main PID: 9487 (python3)
   CGroup: /system.slice/myservice.service
           mq9487 /usr/bin/python3 /home/pi/myservice/main.py

Jan 07 13:48:35 raspibp systemd[1]: Started This is My Service.

停止する

$ sudo systemctl stop myservice.service
$ sudo systemctl status myservice.service
● myservice.service - This is My Service
   Loaded: loaded (/home/pi/myservice/myservice.service; linked; vendor preset: enabled)
   Active: inactive (dead)

Jan 07 13:48:35 raspibp systemd[1]: Started This is My Service.
Jan 07 13:56:45 raspibp systemd[1]: Stopping This is My Service...
Jan 07 13:56:45 raspibp systemd[1]: Stopped This is My Service.

無効化する

$ sudo systemctl disable myservice.service
Removed /etc/systemd/system/myservice.service.
Removed /etc/systemd/system/multi-user.target.wants/myservice.service.
$

参考資料

はてなダイアリーからはてなブログへ

ページだけ作り直しました。

今後の情報発信の体制としては、こんな感じで考えてます。

  • Twitter:その瞬間の思ったことを適当に発信。
  • Hatena Blog:試行の覚え書き(失敗オチも有り)。あと、買いたい本の覚え書き。
  • Qiita:試行のまとめ(基本的に成功したものだけ)。

はてなダイアリー時代から数えて、16年目。

今後どんな感じになるかは分かりませんが、臨機応変に作っていこうと思います。

今後ともごひいきに。