2018年1月17日水曜日

Learning sed for bash cgi processing

開発時には、何回も”ちょっとテスト”必要ですが、、、
今回は、sed使ってcurlで投げた引数の処理
curlで投げた先が、bashというのはご愛敬で、、、

あまりにも、久しぶりのsedを使った処理だったので、メモとして記録

端末側からは、、、

curl -X POST -d "qq=123&aaa=222" http://www.workrobot.co.jp/api/rdcs/v2/mng/robot/net/net_setting

実行結果は、、、
POST
14

key1: qq  value1: 123
key2: aaa  value2: 222

success command

サーバ側のスクリプトは、、、
#!/bin/bash

#touch `/bin/hostname`

#cat - > qq
#cat -  > qq
read STRING

echo $REQUEST_METHOD
echo  $CONTENT_LENGTH
echo
value=`echo "${STRING}" | sed -e "s/.*=\(.*\)/\1/"`
str=`echo "${STRING}" | sed -e "s/\(.*\)=.*/\1/"`
key=`echo "${str}" | sed -e "s/.*&\(.*\)/\1/"`

#echo $str
str2=`echo "${str}" | sed -e "s/\(.*\)&.*/\1/"`
value1=`echo "${str2}" | sed -e "s/.*=\(.*\)/\1/"`
key1=`echo "${str2}" | sed -e "s/\(.*\)=.*/\1/"`
echo "key1:" ${key1} " value1:" ${value1}
echo "key2:" ${key} " value2:" ${value}
echo
echo "success command"

sedの呪文の世界(笑)

Peace!!


MultiProcess or MultiThread

メモメモ、、、、

僕は、自律制御の仕組を開発している。
もう、3年程度たつので、現在のモノをスマートにブラッシュアップしたくていろいろ検討中
内部では、様々な処理をマルチタスクで行っているが、いよいよスパゲティー状態。それと、いろいろなノウハウもたまり、、、

再実装を考えた場合、マルチタスクのシステムなので、
それをどう実現する様に、改めて考えている。
技術的には、マルチスレッドやマルチプロセスなどのテクニックの利用となる。
ネットには、一般論や解りやすい事例は書いてあるけど
自分の技術選択に必要な情報はほとんどない
で、自分で決めるわけだけど、、、
以下は、まとまっていないけど、、、

技術選択基準は、
・堅牢なシステムの実現
・開発効率、特に検証・デバッグのやりやすさ
・システムの拡張のしやすさ

・堅牢性
ロボットのコントローラなので、堅牢な作りにする必要がある。
堅牢とは、、、、
・目的の機能を誤りなく実行し続ける事。
・想定内の異常が発生した場合、所定の手続きで、必要な処置を行い決められた状態に移行する事

人それぞれによって異なる訳で、、、
実際は、システムデザイン、プログラムデザインに係わる事なんだけど、、、
一つのタスクだけで動くわけではないので、
マルチに動くタスクをどのように管理するのか?
それが、重要で、、、
となると、
マルチスレッド、マルチプロセスどちらを上の基準から選択するのか?

自分の堅牢の定義が世間一般的なのかはさておき、、、
マルチタスクの視点から言えば、徹底的なモジュール化をベースに、モジュール結果の評価を正しく行い、次の処理へとつなぐこと。
では、スレッドとプロセスどちらが適しているのだろうか、、

その前に、
マルチスレッドと、マルチプロセスの復習
・マルチプロセスは、複数の独立したプロセスで並列処理する事
・マルチスレッドは、一つのプロセス内で並列処理する事

ブラウザーや、ウェブサーバーはマルチスレッドになっている。
ブラウザーのファイルダウンローなどはスレッド、また画面に現れるダイアログボックスもスレッド。そうしないと、ファイルのダウンロード終了までブラウザーが固まってしまうから、、、時間のかかる処理を別に動かす。また、タグもそれぞれ別スレッド。そうしないとブラウザープログラムで一つのサイトしか表示できない。
Webブラウザーも、アクセスしてくる要求毎にスレッド対応。以前は、fork()だったけど、アクセスが多くなると起動時のオーバヘッドの高いfork()では、感じる遅延が発生する。
この二つの例は、同一機能を並列的に複数行う事と考えても良い。
つまり、機能のクローン化。ダイアログをスレッドかするのは、クローン化というよりは時間差により遅延解消
そうみると、
・機能のクローン化
・時間差処理の外だし
と考えてもよい。
マルチプロセスも、機能のクローン化
両方ともに、良い点や考慮しなければならない事があり、決定的な優劣はつけにくい。

ところで、僕は何の為にマルチタスクにするのか?
それを再度考えると、、、
このような機能構成のロボットコントローラーを開発するのが目的であり、
よくよく構成をみると、マルチプロセスか、マルチスレッドなのか
どちかの技術で決められない事がよく解る。
あさはかな自分、反省


これを、先ほどの求める事などを組合わせて考えると、、、
青いBoxはマルチスレッドで機能クローン化を図った方がよい所、
赤い線の部分は、プロセスとして運用した方が良い所、、、

マルチプロセスと、マルチスレッドの組合せで構成するというのが
先の技術選択基準を満たすと今は考えている。

という事は、今度は、プロセス間通信をどうするかという事だけど、、、
それは、Share Memoryをベースにして同期処理などを取る仕組みを創る事にした。

という事、細かい部分に入りながら、地道な改良を始める

とりとめもない、自分のメモ、、、

Peace!!

2018年1月14日日曜日

how to use Jansson

Janssonインストールしたけど、どう使うのか?
webにも、あんまり細かい事は出ていない
例えば、こんなデータの場合は?

[
{
    "RdcsId":"rcmp-r41",
    "Status":1,
    "NetIdLocal":"kk",
    "Agent":null,
    "Category":"4WD",
    "PlatformRbt":null,
    "NowRole":"tk001",
    "OsVersion":"4957-v7#1047",
    "Role": {
        "Execute": "tk001",
        "LoadId": [
            "tk001", "tk0201", "mv0459"
        ],
        "Status": "Safe"
    }
},
{
    "RdcsId":"rcmp-r42",
    "Status":2,
    "NetIdLocal":"kk",
    "Agent":null,
    "Category":"4WD21",
    "PlatformRbt":null,
    "NowRole":"tk022",
    "OsVersion":"4957-v7#1047",
    "Role": {
        "Execute": "tk001",
        "LoadId": [
            "tk001", "tk2222", "mv0459"
        ],
        "Status": "wait"
    }
},
{
    "RdcsId":"rcmp-r43",
    "Status":3,
    "NetIdLocal":"l0",
    "Agent":null,
    "Category":"4WD23",
    "PlatformRbt":null,
    "NowRole":"tk033",
    "OsVersion":"4957-v7#1047",
    "Role": {
        "Execute": "tk001",
        "LoadId": [
            "tk001", "tk3333", "mv0459"
        ],
        "Status": "Safe"
    }
}
]

こういうデータに対しての使用方法を理解しないと困るので、、、
プログラムを作って、検証した。
で、一応、使い方は理解できたかもという話
インターネット経由のデータ処理が多いけど、プログラムのファイル読み込み部分がcurlのツールになる。
それは、JanssonのTutorialを見ればわかるので、、、
で、結果は、こんな感じで、、、まぁ、自己満足でごめんなさい。
プログラムはこんな感じ、、、
プログラムは、試行錯誤の跡、たっぷり(笑)
あっ
追記:Raspberry Piで、curlモジュール使うとき
sudo apt-get install libcurl4-openssl-dev

Peace!!

-------------- build ------------------------------------
gcc tst4.c -o tst4 -ljansson

-------------- program --------------------------------

#include <stdio.h>
#include <jansson.h>

//#define PRS(A)  printf("----->%s\n", A)

/************************************************/
int main(int argc, char *argv[])
{
    size_t i;
    int iCnt;

    json_t *root;
    json_error_t error;
    
    FILE    *outfl;

    /********************************************
    **     check arguments
    ********************************************/
    if(argc != 8){
        fprintf(stderr, "usage: %s file dumpfile keyword obj child-obj child-obj-array key\n\n", argv[0]);
        return 2;
    }
    
    if ((outfl = fopen(argv[2], "w")) == NULL) {
        fprintf(stderr, "error: file open.(%s)\n", argv[3]);
        return 1;
    }

    /********************************************
    **     convert jansson memory data
    ********************************************/
root = json_load_file(argv[1], 0, &error );
    if(!root){
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
        return 1;
    }

    // check array data
    if(!json_is_array(root)){
        fprintf(stderr, "error: root is not an array\n");
        json_decref(root);
        return 1;
    }

    iCnt = json_array_size(root);
    printf("array counts = %d\n", iCnt);
    
    for(i = 0; i < iCnt; i++){
        json_t *data, *value, *obj, *objv, *obj1, *obj11, *obj111;

        /*****************************************
        **     1. get one object
        *****************************************/
        // get obj
        data = json_array_get(root, i);
        json_dumpf(data, outfl, 256);
        
        if(!json_is_object(data)){
            fprintf(stderr, "error: data %d is not an object\n", (int)(i + 1));
            json_decref(root);
            return 1;
        }

        // get value
        value = json_object_get(data, argv[3]);
        if(!json_is_string(value)){
            fprintf(stderr, "error: obj no. %d: keyword:%s is not a string\n", (int)(i + 1), argv[3]);
            return 1;
        }

        /*****************************************
        **     2. get object in object
        *****************************************/
        // get obj
        obj = json_object_get(data, argv[4]);
        if(!json_is_object(obj)){
            fprintf(stderr, "error: obj %d: is not an object\n", (int)(i + 1));
            json_decref(root);
            return 1;
        }

        // get value obj,obj
        objv = json_object_get(obj, argv[5]);
        if(!json_is_string(objv)){
            fprintf(stderr, "error: objv no. %d: keyword:%s is not a string\n", (int)(i + 1), argv[5]);
            return 1;
        }
        
        /*****************************************
        **     3. get array value in object
        *****************************************/
        // get obj
        obj1 = json_object_get(data, argv[6]);
        //json_dumpf(obj1, stderr, 256);printf("\n");
        if(!json_is_object(obj1)){
            fprintf(stderr, "error: obj1 %d: is not an object\n", (int)(i + 1));
            json_decref(root);
            return 1;
        }

        // get value obj,obj
        obj11 = json_object_get(obj1, argv[7]);
        //printf("------------------------\n");
        //json_dumpf(obj11, stderr, 256);printf("\n");
        if(!json_is_array(obj11)){
            fprintf(stderr, "error: obj11 no. %d: keyword:%s is not a object\n", (int)(i + 1), argv[6]);
            return 1;
        }
        obj111 = json_array_get(obj11, 1);
        if(!json_is_string(obj111)){
            fprintf(stderr, "error: obj111 no. %d: keyword:%s is not a string\n", (int)(i + 1), argv[7]);
            return 1;
        }
        /*****************************************
        **     4. print value
        *****************************************/
        printf("key:%s  value:%s obj:%s obj111:%s\n", 
            argv[3], json_string_value(value), json_string_value(objv),
            json_string_value(obj111));
    }
    
    /*********************************************
    **                                          **
    **     terminate                            **
    **                                          **
    *********************************************/
    json_decref(root);
    fclose(outfl);
    return 0;

}

An installation of Jansson 2.10

jsonをC言語プログラムで扱いたく、、、

色々調べたけど、Janssonを使う事に

1.インストール

まずは、こちらのURLのReleasesのDocumentationをクリック
現れたページのGetting Startedの通りにインストールする
それで、準備完了
追記:Raspberry Piで、curlモジュール使うとき
sudo apt-get install libcurl4-openssl-dev

2.テスト

以下のデータをファイルに保存して、そのファイルを読んでパースをするプログラムで稼働確認

・データ(tst1.json)
{
"RdcsId":"rcmp-r41",
"Status":1,
"NetIdLocal":"kk",
"Agent":null,
"Category":"4WD",
"PlatformRbt":null,
"NowRole":"tk001",
"OsVersion":"4957-v7#1047",
"Role": {
"Execute": "tk001",
"LoadId": [
"tk001", "tk0201", "mv0459"
],
"Status": "Safe"
}
}

・プログラム(ファイル名:tst1.c)

余分な部分は、お許しを、、、

#include <stdio.h>
#include <jansson.h>

int main( int argc, char *argv[] ){
json_error_t error;
json_t   *infl;
json_t   *string;

infl = json_load_file(argv[1], 0, &error);

if(NULL != infl) {
string = json_object_get(infl, argv[2]);
if(NULL != string) {
if( json_is_string(string)) {
printf("%s:%s\n", argv[2], json_string_value(string));
}else {
printf("error1\n");
}
}else{
printf("error2\n");
}
}else{
printf("file open error:%s\n", argv[1]);
}

json_decref(string);
json_decref(infl);

return 0;
}

・build
gcc tst1.c -o tst -ljansson

・excute
./tst1 tst1.json Category

Category:4WD

Peace!!

2018年1月10日水曜日

An installation of MongoDB3.x on Raspberry Pi3 Arch Linux ARM64bt

MongoDBのインストールは、いたって簡単


sudo pacman -S mongodb mongodb-tools
[sudo] password for pi:
resolving dependencies...
looking for conflicting packages...

Packages (9) gperftools-2.6.2-1  libstemmer-0+337-2  libunwind-1.2.1-1
             lsb-release-1.4-14  snappy-1.1.7-1  wiredtiger-2.9.3.20171205-2
             yaml-cpp-0.5.3-3  mongodb-3.6.1-2  mongodb-tools-3.6.1-1

Total Download Size:    52.21 MiB
Total Installed Size:  223.88 MiB

:: Proceed with installation? [Y/n] y
:: Retrieving packages...
 snappy-1.1.7-1-aarch64    22.5 KiB   281K/s 00:00 [######################] 100%
 libunwind-1.2.1-1-a...   100.2 KiB   556K/s 00:00 [######################] 100%
 gperftools-2.6.2-1-...   556.7 KiB  1136K/s 00:00 [######################] 100%
 libstemmer-0+337-2-...    52.1 KiB   868K/s 00:00 [######################] 100%
 yaml-cpp-0.5.3-3-aa...   150.0 KiB   882K/s 00:00 [######################] 100%
 lsb-release-1.4-14-any     6.7 KiB  0.00B/s 00:00 [######################] 100%
 wiredtiger-2.9.3.20...   641.6 KiB  1126K/s 00:01 [######################] 100%
 mongodb-3.6.1-2-aarch64   34.8 MiB  4.56M/s 00:08 [######################] 100%
 mongodb-tools-3.6.1...    15.9 MiB  1917K/s 00:09 [######################] 100%
(9/9) checking keys in keyring                     [######################] 100%
(9/9) checking package integrity                   [######################] 100%
(9/9) loading package files                        [######################] 100%
(9/9) checking for file conflicts                  [######################] 100%
(9/9) checking available disk space                [######################] 100%
:: Processing package changes...
(1/9) installing snappy                            [######################] 100%
(2/9) installing yaml-cpp                          [######################] 100%
(3/9) installing lsb-release                       [######################] 100%
(4/9) installing libunwind                         [######################] 100%
(5/9) installing gperftools                        [######################] 100%
Optional dependencies for gperftools
    graphviz: pprof graph generation
    gv: pprof postscript generation
(6/9) installing wiredtiger                        [######################] 100%
(7/9) installing libstemmer                        [######################] 100%
(8/9) installing mongodb                           [######################] 100%
==> Warning: the 32 bit version of MongoDB is limited to about 2GB of data.
==> See http://blog.mongodb.org/post/137788967/32-bit-limitations
Optional dependencies for mongodb
    libpcap: needed for mongosniff [installed]
    mongodb-tools: mongoimport, mongodump, mongotop, etc [pending]
(9/9) installing mongodb-tools                     [######################] 100%
:: Running post-transaction hooks...
(1/1) Arming ConditionNeedsUpdate...

sudo systemctl enable mongodb.service
Created symlink /etc/systemd/system/multi-user.target.wants/mongodb.service -> /usr/lib/systemd/system/mongodb.service.

sudo systemctl start mongodb.service
mongo
MongoDB shell version v3.6.1
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.1
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-01-10T09:55:46.469+0900 I STORAGE  [initandlisten]
2018-01-10T09:55:46.469+0900 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2018-01-10T09:55:46.469+0900 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2018-01-10T09:55:46.919+0900 I CONTROL  [initandlisten]
2018-01-10T09:55:46.919+0900 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-01-10T09:55:46.919+0900 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-01-10T09:55:46.919+0900 I CONTROL  [initandlisten]
2018-01-10T09:55:51.134+0900 E -        [main] Error loading history file: FileOpenFailed: Unable to fopen() file /home/pi/.dbshell: No such file or directory
> help
        db.help()                    help on db methods
        db.mycoll.help()             help on collection methods
        sh.help()                    sharding helpers
        rs.help()                    replica set helpers
        help admin                   administrative help
        help connect                 connecting to a db help
        help keys                    key shortcuts
        help misc                    misc things to know
        help mr                      mapreduce

        show dbs                     show database names
        show collections             show collections in current database
        show users                   show users in current database
        show profile                 show most recent system.profile entries with time >= 1ms
        show logs                    show the accessible logger names
        show log [name]              prints out the last segment of log in memory, 'global' is default
        use <db_name>                set current database
        db.foo.find()                list objects in collection foo
        db.foo.find( { a : 1 } )     list objects in foo where a == 1
        it                           result of the last line evaluated; use to further iterate
        DBQuery.shellBatchSize = x   set default number of items to display on shell
        exit                         quit the mongo shell
> exit

bye

PEACE!!

Raspberry Pi3 ArchLinux ARM64bit vs Raspbian 32bit

同じ機種に、違うOS、それも64bit と 32bit インストールしたら
パフォーマンスは、知りたくなるのは人情

で、
上が、ArchLinux ARM64bit
Linux 4.14.12-1-ARCH #1 SMP Fri Jan 5 17:28:52 MST 2018 aarch64 GNU/Linux
gcc version 7.2.1 20171128 (GCC)


下が、Raspbian 32bit 
Linux  4.9.73-v7+ #1072 SMP Sun Dec 31 19:37:41 GMT 2017 armv7l GNU/Linux
gcc version 4.9.2 (Raspbian 4.9.2-10)

ベンチマークプログラム結果は、こんな感じ
プログラムの詳細は、基本はそれぞれの型で繰り返し

最後の2段は、それぞれ
浮動小数点値の平方根の計測
・3次元ベクトルの単位ベクトル計算の計測

さぁ、これをどうか評価するかはあなた次第。

因みに、32bit Archlinux,では、Raspbianの方がおおむね30%性能が良い
やはり、本家のチューニングでしょうか?

Peace!!



An Installation of ArchLinux ARM64bit on RaspberryPi3

ロボットの運用管理は、RDCS クラウドでするのだけど、、、
日本中どこでも、Broad Bnadがある訳ではないくて、
ローカルRDCSサーバーを置く必要もあり。

で、MongoDBを使う関係で3.xは64bit OSが必要な訳で、、、
Raspbianは、シングルimageなので、、、
Arch Linux ARM64bitのインストールをする事に

OSも、バーションが上がっておりこのブログで書いたインストール方法は古くなり、シックハックしながら、、、その記録

このページをよく読んで実施する。というか、Bootディスクを作る核は、この手順。

https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-3

1.基本的な流れ

稼働中のRaspberry PiにSDメモリーリーダをUSB接続して、ダウンロードしたArchlinux64のBoot用 SDメモリーを作成する。
Boot用のSDメモリーが出来れば、まずはwifi経由のssh接続で環境を作っていく。だから、wifi設定とssh接続は最優先


出来たSDメモーで起動すると、aarch64が起動画面に表示される。
Arch Linux ARM64bitの証拠


2.SDメモリーを正しく認識させる


SDカードは、全ての領域が使えるように、あらかじめフォーマットなどの処理を行う。新品ならそのままで大丈夫

上図は、16GBのSDカードメモリーが/dev/sdaとして認識されている状態をしめす。このように独立したデバイスとして認識されている事が最初の一歩。
この表示コマンドは、fdisk

sudo fdisk -l

これ以降は、ArchLinuxのインストールページの手順そのままなので、そちらを参照してください。
回答する時に利用するコマンド、bsdtar はインストールが必要だと思います。

https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-3

3.起動

上記で作成したSDメモリーをRaspberry Piに挿入、イーサーネット接続、HDMIディスプレイーおよびキーボード接続して電源を投入する。
これで問題が無ければ、起動する。

初期設定で、2つのユーザが使えるようになっている。
root、alarmである。初期パスワードも同じ。
rootで、loginして以下の処理をまず行う。

pacman -Syu
reboot 

3.1 ssh   (rootで処理)

設定作業を楽にする為にsshdの起動を行う。
systemctl enable sshd.service
systemctl start sshd.service

/etc/ssh/ssh_configを確認して、変更があれば変更する
デフォルトのままで使えます。

3.2 無線LAN接続   (rootで処理)

pacman -S wpa_supplicant
wifi-menu wlan0
sudo vi /etc/netctl/wlan0-SSID名称

#IP=dhcp
IP=static
Address='192.168.11.152/24'
Gateway='192.168.11.1'
DNS=('192.168.11.1')

wifi-menu wlan0では、SSID名を指定してkeyを入力する。
自動的に/etc/netctlにファイルが生成される
固定IDで使うので、そのファイルを上記のように編集する。

netctl enable wlan0-SSID名称
reboot

ここまで正常に終わると、指定したSSIDのwifiネットで他のマシンからssh接続で、様々な処理が可能となる。

Peace!!

おまけ
・sudoを設定する。rootを直接使わない
sudo pacman -S sudo
vi /etc/sudoers

以下の行のコメントを外す
## Uncomment to allow members of group wheel to execute any command
%wheel ALL=(ALL) ALL

・新しいユーザ(pi)をつくり、パスワードを設定する
sudo useradd -G wheel -m -c "Pi User" pi
sudo passwd pi


終わり
・Localeの件
sudo vi /etc/locale.gen
sudo locale-gen
sudo locale-gen
sudo echo LANG=en_US.UTF-8 > /etc/locale.conf
export LANG=en_US.UTF-8