20191201のLinuxに関する記事は8件です。

THETAにお手軽Linux環境を内包させる

この記事は IoTLT Advent Calendar 2019 の2日目の記事です。

はじめに

リコーの @KA-2 です。

弊社ではRICOH THETAという全周囲360度撮れるカメラを出しています。
RICOH THETA VRICOH THETA Z1は、OSにAndroidを採用しています。Androidアプリを作る感覚でTHETAをカスタマイズすることもでき、そのカスタマイズ機能を「プラグイン」と呼んでいます(詳細は本記事の末尾を参照)。

と、定型文をかきつつ、、、
今回の記事はプラグインの仕組みや知識を利用した新しいTHETAカスタマイズ方法についてまとめました。
タイトルをみて「adb shellの話?」と思った方、「遠からず」ですが、もっと自由度がある環境にする話です。

adb shellを上手に利用したAndroidアプリをTHETAにインストールします。そうすると、使い心地はLinux(ssh、apt、git、wgetなども使え、多言語開発可能)。root不要。これまでの使い方と完全共存。切り替え簡単。そんなTHETAコンピューティングが可能になります!
「THETAでこんなことを試してみたい」と思いついてから動くまでが圧倒的に速くなる。THETAがとてもハッカソン向きになる。そんな内容です。

「ロボット着ぐるみの内側にいるペンギンさん」の力を自由に引き出せるようにするのですが、アブナイハナシではありません。安心して頂くため、先に説明します。

今回利用するのはTermuxというアプリです。このアプリをインストールすると、sandbox内(システムが安全に保たれるアプリ固有領域)にお手軽Linux環境が展開されます。あとはCUIでその環境を使いこなすだけです。
Termux開発コミュニティさんは、Google Play だけでなくF-Doroid(ある側面で一番セキュア)にも公式apkを公開しています。このおかげで「THETAを開発者モードにした方はその恩恵を受けられる」というわけです。

このアプリはTHETAにとって、(何ものにもなれるの意図で)万能THETAプラグインと見なせます。THETAを開発者モードにした人のワイルドカードです。

  • もうわかった!という方、自力で始めちゃってください。この記事は困ったときに必要な箇所だけみればOK。
  • ちょっと自信はないけどLinuxということならトライしたいという方、前半戦は丁寧めに書いておきます。各プラットフォーム用のSFTP対応ファイル管理アプリからファイルの読み書きする仕込みはできると思います。興味次第では「コマンドを打てば響くTHETA」を体感してから、コマンドの羅列でシェルスクリプトとか短いPythonあたりのスクリプト言語を体感するのも良さそうです。
  • ラズパイなども含めたLinux系コンピューター経験ありだけど「Androidアプリ開発環境はわからないなぁ」とTHETAいじりを躊躇していた方、劇的に敷居が下がります!THETA自体がラズパイみたいになります。慣れた環境から少しづつAndroidの仕組みに触れ、THETAプラグインやAndroidアプリも作成できるようになれると思います。
  • THETAプラグインきっかけでAndroidアプリ開発環境に触れはじめた方(ワタシはこれ)、THETA固有の仕組みやAndroidへの理解が深まります。なんとなく雛型にしてたTHETA Plug-in SDKの仕組みがわかり、THETA plug-inライブラリに頼らなくて諸々できるとことが体感できます。

レッツTHETAコンピューティング!

THETAまわりで事前に準備が必要なこと

THETAプラグイン開発をしていた方々は既にできています。
今回の記事は、そうでない方々の目にとまりそうなので改めて羅列しておきます。

THETAプラグインのしくみ

今読まなくてもOKです。
2018年10月20日に行われた「RICOH THETA プラグイン開発 ワークショップ #1」資料 の18~21ページです。
考え事ができたとき、仕組みを思い出すと自力で解決できると思うので掲載します。
今回に限らず、普通のTHETAプラグイン作りにも役立つ資料です。

資料抜粋.png

ポイントは以下です。

  • 撮影アプリ(com.theta360.receptor)がTHETA固有事項を担っている
  • 本体ボタン操作なども撮影アプリが受け付けたあと、プラグインへIntentを投げている
  • その他のデバイス固有事項(LEDやOLEDなど)も、プラグインから撮影アプリにIntentを投げると操れる
  • THETA Plug-in ライブラリは撮影アプリ-プラグイン間の上記通信をラップしたもの。通信の詳細はこちらのドキュメント「Broadcast Intent」に掲載されています。
  • プラグインからの撮影方法は2通り
    (1) webAPIが全て使える(内部通信のため、IPアドレス127.0.0.1、ポート8080となる)
    (2) 一般AndroidアプリのようなCameraAPIを使う方法で高速連写など特殊な撮影も可能ですが、細かなところまで自身でコードを書かなければなりません。

Termux について

「はじめに」の章にTermux公式Wikiへのリンクが貼ってありますが英語です。日本語で概要を掴みたい方は以下あたりをご参照ください。

いつでもLinuxコマンドが使える!Androidで動くLinux端末「Termux」【Root化不要】

他にも「Termux」で検索すると日本語の記事も沢山ヒットします。QiitaでTermuxタグがついた記事も豊富です。Google Playでは2019年11月時点で500万ダウンロードもされている人気ツールです。
活発な機能拡張が続いているので、GitHubのソースコードやその他のやり取りからも多くのことが読み取れますよ。

Linuxとの違いについては公式Wikiのこちら

余談ですが、今年の夏「Maker Faire Tokyo 2019」にて「Linuxで開発したいなぁ~」「Python動けばなぁ~」のような声を伺えました。そのおかげで今更ながらこのツールに気づけました。探してみるものですね。

Termuxインストール

事前説明ながくてすみません、やっと作業です。
「はじめに」の章に記載済みF-DoroidのTermuxページから最新のapkファイルをダウンロードしてください。クリックする場所が紛らわしいのでご注意を。

ダウンロード説明.png

ファイル名は「com.termux_82.apk」(2019年11月中旬時点)のようになっていると思います。数字はリリースバージョン番号です。大きな数字ほど最新です。
ダウンロードできたら、Android StudioのTerminalまたは Windowsならばコマンドプロンプトから

adb install -r (ファイルまでのパス)\com.termux_82.apk

と入力するとインストールできます。
(以降「adb」ではじまるコマンドは、この方法で実行すると思ってください。その他についてはTermuxへの入力です。)

はい、これであなたのTHETAにLinux環境が入りました。簡単ですね。

これ以降は、動作を確認しながら使い勝手をよくしていきます。

Termux初期セットアップ

THETAとPCをケーブル接続するのではなく無線LAN経由でTHETAにログインして利用できると物事が捗ります。ラズパイはじめLinux系ボードコンピューターでは常套手段ですね。まずはその環境を整えるのがメインの作業です。それに加えて、最初に行ったほうがよさそうな事項を記載しておきます。

THETAプラグインを作れる方々には既知の事項が多数あります。
各人の理解度に併せ、読み飛ばしたり、作業順を適宜入れ替えたりのアレンジはお任せします。

THETAをPCとUSB接続中にwifi利用可能にしておく

THETAプラグインを作りなれている方は既にしてあると思います。
こちらのadbコマンドを打って、事前にTHETAをPCにUSBケーブルで接続している状態でもTHETAのwifiが使える状態にしておいてください。
この設定は、一度実施すると、パラメータをfalseにしたコマンドを打つか、工場出荷状態に戻すまで維持されます。

THETAの無線LANクライアントモード(CLモード)を設定しておく

Termux環境へのインストールが必要なので、THETAを外部ネットワークに接続できるアクセスポイントへ接続しておいてください。
これは通常の使い方で予め仕込んでおきます。このあたりの動画こちらの動画が参考になります。

ご家庭のルーターに繋いでもよいですし、スマートフォンをテザリングの状態にしてTHETAからスマートフォンへ接続するでもよいです(通信料にはご注意を)。
複数の接続先を覚えておけます。

Vysor環境でキーボードが使える状態にする。

THETAをPCとUSBケーブル接続しVysorの画面にTHETA内部が見える状態にしてください。

001_Vysor.JPG

この状態では、Vysorからはキーボード入力をうけつけないので、こちらのadbコマンドを打って、Vysor環境でキーボード入力ができる状態にします。
このコマンドで行っていることは、「THETAプラグインのしくみ」の章に記載がある「撮影アプリ(com.theta360.receptor)」の一時停止です。再開はシャッターボタン長押し、資料に記載のコマンド、完全電源OFF後の電源ONで行えます。

VysorからTermuxを起動する。

Termuxを起動すると以下画像右側のような画面が表示され、ソフトキーボード入力 や PCのキーボード入力ができる状態になっています。

002_Termux起動2.JPG

apt(pkg)使えます

「外部から必要なパッケージをインストールできる」これがadb shellよりもTermux環境を使う大きな利点となります。そのパッケージ管理ソフトがaptです。aptの管理情報を最新の状態にする作業です。

apt update
apt upgrade

と2つのコマンドを実行してください。
[Y or N]を問われたらYを答えればOKです。
何かのインストールを行う前には、その都度実施する癖をつけておくとよいです。

(余談:pkgも使えます。Termux環境のpkgはaptのラッパーで中身は同じものとのことです。)

テキストエディタのインストール

プログラムを書かない人であっても、僅かながら設定ファイル(テキストファイル)の編集作業が必要となります。
Termuxをインストールしただけの状態でviエディタが使えますが、vimやEmacsやnanoもインストールして使えます。(viって何?vimって何?という方は無難にnanoをインストールしておくと良いです。)

例えば、nanoをインストールする場合は

apt install nano

と打てばOKです。
お好みに応じてインストールし、エディター自体の設定ファイルも編集しておくと便利です。(私はvimで~/.vimrcにset numberと記載しておき、行番号を表示させています。nanoの場合は/etc/nanorcにset linenumbersと記載しておけば同じ感じです。)

ストレージへのアクセス権を与える

この時点でTermuxに読み書き権限があるのは、自身のアプリケーション領域だけで窮屈です(THETAでは、他のアプリ領域も含め最大2GBに制限されています)。そこで、撮影画像が保存される領域(adb shellでは/storage/emulated/0/DCIM配下)への読み書き権限を与えます。
いつでもできますが、Vysorの画面が使えるときにやってしまいましょう。

まず、Vysor画面 Settings → Apps → Termux から、Termuxにストレージアクセスのパーミッションを与えます。

003_パーミッション.JPG

続いて、ターミナルから以下のコマンドを打ちます。

termux-setup-storage

すると、読み書き権限がつくだけでなく~/storage配下にシンボリックリンクができます。
「ls -al ./storage」などを打って確認するとよいでしょう。
「~/storage/dicm」が「/storage/emulated/0/DCIM」と等価です。
(余談となりますが、/sdcard/DCIM は /storage/emulated/0/DCIM のシンボリックリンクです)

004_ストレージ設定.JPG

もし、ストレージアクセスのパーミッションを与えずにこのコマンドを打った場合には、ダイアログが表示されるので「ALWAYS」に答えてから、もう一度同じコマンドを打てばOKです。

このブロックの作業は以上。
ファイルアクセスに関するちょっとした注意事項は本記事後半「SFTP関連Tips集」にまとめてあります。
今は次の作業へすすみましょう。

SSHサーバーまわりの整備

TermuxではOpenSSHが使えます。
以下手順でインストールとセットアップをしてください。

  1. OpenSSHのインストール(apt install opensshを打つだけ)
  2. 秘密鍵&公開鍵ペアの生成(THETA初期設定では、外部機器で生成を推奨)
  3. 公開鍵を ~/.ssh/authorized_keysに仕込む(直接コピペ推奨)
  4. ~/.bashrcを作成して1行「sshd」とだけ書いておく
    (.bashrcはシバンなしでも大丈夫みたいです)

1~3については、以下ページなど(他も多数あります)を参考とすると良いです。

ただし、以下の点を補足しておきます(上の記事より先に見てね)。

  • 2.について
    Termux以外で行うほうが判りやすく操作がラクです。「SSHでのログインを試す」の項で紹介するようなSSH対応クライアントアプリで生成できます。 どうしてもこの時点で、THETA内Termuxで生成した鍵を使いたい方は、こちらの応用で生成したファイルをとりだせます。
  • 3.について
    この段階では、外部機器で作成した公開鍵のファイルをTermuxが参照できる領域にコピーすることが困難です。しかし、公開鍵は文字列が1行だけかかれているテキストファイルなので無理にコピーしようとは思わず、Termux上のエディタで直接~/.ssh/authorized_keysに文字列をコピペするのが最速作業手順かと思います。
  • 4.について
    この作業は、Termuxが起動したらSSHサーバーが自動で立ち上がるようにするための設定です。Termux環境はこれができるのがTHETAにとって最大の利点かもしれません。このシェルスクリプトの記述しだいで様々な振る舞いにできます。まさに「万能THETAプラグイン」です。

ここまででUSBケーブル接続した苦行環境はおしまいです。

TermuxへSSHでログインする

ここからは、THETAとPCを接続していたケーブルを抜いて作業します。

クライアントアプリの紹介

THETAにログインする端末毎に、SSHログインできるクライアントアプリを紹介しておきます。
(前述のとおり、これらのアプリでも秘密鍵と公開鍵のペアが作成できます。)

端末のプラットフォーム クライアントアプリ参考情報
Andoid ConnectBotが無難なようです。他もあります。
iOS 私の知識がありませんがこのあたりを参考に。多数あります。
Windows TeraTermが知らない人居ないレベルでしょうか。他も多数あるかと。
Mac terminalでOpenSSHが使えるはずです。他もあるようです。

クライアントアプリの設定

クライアントアプリの設定で注意することは以下です。

設定項目 設定内容や注意事項
IPアドレス APモードなら192.168.1.1
CLモードはルータによります。(表の下で補足します)
ポート番号 8022になります。
(指定する場合、Termux都合で1024番より大きな数値にしてください)
ユーザー名 空白以外なら何を入れてもOK。
Termuxが自動割り当てして変換してしまいます。
前の作業で作成した秘密鍵のファイルを与えてください。

CLモードで接続する場合の補足です。
THETAにケーブル接続してTermuxのターミナルから「ip -4 a」を打って調べる方法もありますが、毎回ケーブル接続するのは不便です。
ケーブル接続せずにTHETAに割り当てられたIPアドレスを知る方法をいくつか挙げておきます。

接続形態 方法の例
個人用のルーターに接続する ルーターの管理画面で確認することができます。(詳細は機種によるので割愛)
テザリング可能なスマートフォンに接続する スマートフォンのWiFi設定確認画面で確認できます。(詳細は機種によるので割愛)
接続形態によらず、THETAにSSHログインする端末側でLinux系のネットワークコマンドが使える場合

(AndroidスマートフォンにTermuxをインストールするのもありです)
さまざまなコマンドで調べる方法があります。たとえば「nmap -sT -p8022 192.168.*.* 」で8022のポートを開いているTCPプロトコルのIPアドレスを探索するなどです。他arpコマンド利用などもあると思います。

Termuxを起動プラグインにする

通常のTHETAプラグインと同じ操作でTermuxを起動できるようにします。
以下動画の「setup」の所とやり方は同じです。(実は、この動画のプラグイン一覧が表示されるところに「Termux」がみえてるんですよ!探してみてください。)
PC用基本アプリだけでなく、スマートフォンの基本アプリからも設定できます。

THETA Z1をお使いの方は、起動プラグインをTermuxにするのではなく、この動画の Plug-in Launcher for Z1を仕込んでおくほうが便利です。

SSH接続する

準備が整ったらSSH接続してみましょう。
Android機からConnectBotで接続する例を以下に示します。

ログイン.gif

丁寧に手順や仕込みを書いてきたので面倒そうにみえますが、簡単でしょ?

Termuxの終了

Termuxを起動したままSSHをログアウトする方法について説明は不要だと思います。(アプリにより異なります。ターミナルからexitを打つなり、GUIで切断の操作をするなり様々ですが、いずれも簡単です。)

しかし、TermuxはTHETA本体のボタン操作を受け取れません。
このため、Termuxを終了させるためにSSHログインした状態で以下コマンドを打つ必要があります。

am broadcast -a com.theta360.plugin.ACTION_FINISH_PLUGIN --es packageName com.termux

こちらのドキュメント末尾付近「Notifying Completion of Plug-in」に記載があります。

コマンド打つのが面倒という方の強制終了方法として、「電源ボタン短押し」でTHETAをスリープさせることでTermuxを終了させ、すぐスリープから復帰という荒業もあります。

工夫なしで、こんなにTHETAを操れる

外部機器(スマートフォンやPC)からTHETAにSSHログインしてTHETAを操れる環境が整いました。
コマンドラインでできることは必ずプログラムにできます。コマンドラインから少しづつTHETAを操って、振る舞いを確認してみましょう。

この章で紹介することは「プログラミングなし」です。
プログラミングなしでこんなに遊べます。

いきなりLチカ

THETA Vをお持ちの方限定、みんな大好きLチカが簡単にできます。
まずは以下のコマンドを打ってみましょう。

am broadcast -a com.theta360.plugin.ACTION_LED_BLINK -e target LED3 -e color yellow --ei period 500

はい、無線LANの状態を示すLEDが500ms間隔で黄色くチカチカしましたね。

消す場合は以下です。

am broadcast -a com.theta360.plugin.ACTION_LED_HIDE -e target LED3

黄色に点灯させたままは以下です。

am broadcast -a com.theta360.plugin.ACTION_LED_SHOW -e target LED3 -e color yellow 

こちらのドキュメント「Control the LEDs」のブロック を参考にして他のLEDもチカチカさせてみましょう。

  • LED3~8が操れます。
  • LED4~LED8は、カラーLEDでないので色表示ができない(指定不要)
  • 点滅時間の最小値は500[ms] 最大値は 2000[ms]

というくらいが注意点です。

いきなりOLED表示

THETA Z1をお持ちの方、自由に操れるLEDが無いからLチカできないと嘆かないでください。
もっとよい表示デバイスがついていますね。そうOLEDです。
これもコマンド1行で操れるのです。まずは以下を

am broadcast -a com.theta360.plugin.ACTION_OLED_TEXT_SHOW -e text-middle 'This is text-middle String'
am broadcast -a com.theta360.plugin.ACTION_OLED_TEXT_SHOW -e text-bottom 'This is text-bottom String'

消したい場合は以下です。

am broadcast -a com.theta360.plugin.ACTION_OLED_HIDE

こちらのドキュメント「Control the OLED」のブロック が参考になります。

現時点では画像表示に関する以下インテントについて探り中です。
“com.theta360.plugin.ACTION_OLED_IMAGE_SHOW”
“com.theta360.plugin.ACTION_OLED_IMAGE_BLINK”
amコマンドで画像データを渡す方法がまだみつかっていません。。。

OLED表示ちょっと応用

表示器があるTHETA Z1独自の小技となります。
THETA Z1をCLモードにしてTermuxを利用する際、Termuxを起動したらSSHログインするためのIPアドレスがOLEDに表示されていると便利です。

まずはコマンドラインから以下を打ってみてください。

ip -4 a

こんな表示がされると思います。(以下はAPモードの時の例)

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group def ault
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
6: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 192.168.1.1/24 brd 192.168.1.255 scope global wlan0
       valid_lft forever preferred_lft forever

この表示結果を grepコマンドを併用して必要部分のみ抜き出す例は以下となります。
(もっとスマートな方法があるかもしれませんが・・・取り急ぎ)

ip -4 a | grep inet | grep wlan0 | grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(?=\/)'
THETAのWLAN状態 上記コマンドの実行結果
APモード 192.168.1.1
CLモードで接続中 ルータに割り付けられたTHETA Z1のIPアドレス
WLANオフ or
CLモードで未接続
表示なし

が表示されると思います。

このコマンドの結果をOLED表示するように .bashrc を記述しておきましましょう。
すでに記載済みの 「sshd」と併せると以下のような記述になります。
(Termuxの.bashrcは、シバンが無視されるようですが、念のためTermux環境用のシバンを書いておきます。通常のシバンを通す方法はこちらなどが参考になります)

.bashrc
#!/data/data/com.termux/files/usr/bin/sh

# launch sshd
sshd

# display self IP
array=$(ip -4 a | grep inet | grep wlan0 | grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(?=\/)')
echo $array
am broadcast -a com.theta360.plugin.ACTION_OLED_TEXT_SHOW -e text-bottom $array

動作させるとこんな感じ。(CLモードの例)

IPアドレス表示.gif

CLモードでtermuxを利用するのがとても便利になったと思います。

THETAにプリセットされた効果音を鳴らす。

以下のコマンドを打ってみてください。

am broadcast -a com.theta360.plugin.ACTION_AUDIO_SHUTTER

撮影音が鳴りましたね。

こちらのドキュメント「Controlling Speakers」のブロック を参考にして他のプリセット音も鳴らしてみましょう。

「ACTION_AUDIO_ほにゃらら」の「ほにゃらら」を変えるだけで色々な音がなります。

いきなり撮影(curl)

Termuxはインストールするだけでcurlコマンドが使えます。
THETA S/SC/V/Z1にcurlコマンドが使えるPCやラズパイなどを接続して撮影していた方、その知識まるごと生かせます。
今回は、THETA内Termux → THETA内部処理(撮影アプリ) への指示となるので、IPアドレスとポート番号を「192.168.1.1:80」から「127.0.0.1:8080」に変えるだけです。以下コマンドを打ってみてください。

curl -v -H "Content-Type: application/json; charset=utf-8" -H "X-XSRF-Protected: 1" -X POST -d "{"name": "camera.takePicture" }" http://127.0.0.1:8080/osc/commands/execute

撮影の前後で「ls ~/storage/dcim」を打って画像ファイルが増えることを確認してみるとよいです。

その他の色々なこともできます。
webAPIの詳細はこちらをご参照ください。

これでTermuxから殆どのことが掌握できていることになります。
(ライブビューの処理もAndroidより作り易いです。MOTIONJPEGのストリームをffmpegにいれてあーたらこーたらを別プロセスで処理させつつ...とか作り易いです。)

Tips:Termuxのamコマンドは何者?

余談となります。
amコマンドは「Activity Manager」と呼ばれ、AndroidのADB Shell独自のコマンドです。普通のLinuxにはありません。これが何者なのか少し確認してみましょう。

Termuxで「which am」と打つと

/data/data/com.termux/files/usr/bin/am

と結果がでます。

ADB Shellでは

/system/bin/am

と表示されます。

それぞれの使い方で別のバイナリが実行されています。
ヘルプを表示させると、Termuxのamコマンドはアプリケーションの実行権でできる範囲に機能が絞られていることがわかります。「force-stop」などは使えないので、ある意味安全とも言えます。

SFTPクライアントからデータの読み書きをする。

curlコマンドで撮影したあと、lsコマンドで画像ファイルができていることを確認できますが、画像を見れない歯がゆさがあります。
SSHログインしている端末で画像データみたいですよね。これもできます。
iOSだけの困りごとになりますが、DNGファイルをスマートフォン用基本アプリでひきとれませんよね。これもできるようになります。
自身が作成したプログラムが扱うデータなどを、THETA内部に書き込みたかったりもしますよね。これもできます。

SFTPクライアントの紹介

各プラットフォームそれぞれ、SFTP対応アプリはたくさんあるので、いくつかだけ紹介しておきます。

端末のプラットフォーム クライアントアプリ参考情報
Andoid AndFTPがおすすめなようです。普段お使いのファイル管理アプリが既に対応しているケースも。
iOS FTPManagerがおすすめみたいです。iOSを使う人に試してもらったらjpg,DNG,mp4のサムネイルまで表示されました。すごい。
Windows WinSCPを使ってみました。SSHログインも同時に行える特徴があります。他多数あるのでお好みで。
Mac GUIでとなるとちょっと私の知識不足。割愛させてください。

Termux OpenSSHのSFTP設定

Termux Wiki 「Remote Access」ページの「Setting up password authentication」のブロックにしたがって作業します。

・設定ファイルの編集
sshdの設定ファイルを以下のように変更してください。
(SFTPについてはパスワード認証になります)

$HOME../usr/etc/ssh/sshd_config(編集前)
SendEng LANG
$HOME../usr/etc/ssh/sshd_config(編集後)
SendEng LANG
PrintMotd no
PasswordAuthentication yes
PubkeyAcceptedKeyTypes +ssh-dss
Subsystem sftp /data/data/com.termux/files/usr/libexec/sftp-server

・パスワードの設定
以下コマンドを打ってパスワードを設定します(指示に従い2回入力)

passwd

上記2つの設定をしたら、sshdを立ち上げなおします。「pkill sshd」などとすると、現在作業中のターミナルの通信が切断されますので、ログアウトしてログインするのが良いでしょう。

SFTPでファイルアクセスする。

あとは、接続するだけでGUIのファイル管理ソフトで読み書き自由にできてしまいます。
大抵の場合、アプリケーション内にパスワードを記憶できるのでクリックするだけです。

AndFTPからアクセスした例は以下

SFTP.gif

ログイン→ファイル取得→THETA基本アプリで表示までしています。

SFTP関連Tips集

みえすぎちゃって困るの

おおむね、Android Studioの「Device File Explorer」と同じディレクトリが見えます。ファイルについてはアプリケーションとして権限があるところまでなので、空のディレクトリが見える場合もあります。

見えすぎても使いませんので、クライアントソフト側で「接続したときに最初に表示するディレクトリ」を設定しておくと便利です。各人の用途によりけりですが、$HOMEや/sdcard/DCIM としておくのが無難です。

USBケーブル接続(PTP/MTPアクセス)との違い

USBケーブル接続時(UVCモード以外)のプロトコルはPTP/MTPで、外部機器からのアクセス制限は以下となっています。

  • Androidのシステムからみた /sdcard/DCIM 配下が見えます。
  • 拡張子が jpg, DNG, mp4 のファイルだけ見えます。
  • 読み取りと削除ができます。書き込み禁止です。

上記に該当するファイルのデータベースは完全電源OFFから電源ONしたときと撮影アプリ(com.theta360.receptor)によってファイル操作されたときに更新されます。
撮影アプリを介さず作成/削除された対象ファイルを、完全電源OFFをせずに、PTP/MTPから最新の状態が見えるようにするには、こちらのドキュメント下方「Updating the Database」に記載されているインテントを使う必要があります。

/sdcard/DCIM/orgdir/newfile.jpg のようなファイルを作成した場合

am broadcast -a com.theta360.plugin.ACTION_DATABASE_UPDATE --esal targets DCIM/orgdir/newfile.jpg

/sdcard/DCIM/orgdir/delfile.jpg のようなファイルを削除した場合

am broadcast -a com.theta360.plugin.ACTION_DATABASE_UPDATE --esal targets DCIM/orgdir/delfile.jpg

「DCIM」始まりで対象ファイルまでのパスを指定します。
ファイルが空のディレクトリの追加や削除に対しては、完全電源OFF→電源ONでないと更新されないようです。
「PTP/MTP接続時、電源OFFせずにTermuxで処理したjpg, DNG, mp4ファイルをみたい」という場合だけの話なので、あまり気にしなくても問題ないかもしれません。

THETA内部のタイムゾーン

一般的なTHETAの使い方には、タイムゾーンの概念がありません(Exifなどの仕様にありません)。
Termuxを使うケースに限らず、開発者モードにして、タイムゾーンの概念があるAndroidシステムを介するプログラミングをするとタイムゾーンが気になることがあります。
今回、SFTPクライアントでTHETA内部のファイルタイムスタンプをみたり、「date」コマンド打ったりすると、THETA内部がタイムゾーンをどのように扱っているか簡単に見えるので、THETAの振る舞いに触れておきます。

THETAは、「AndroidのタイムゾーンをUTCに固定して、時刻部分は各国の時間(基本アプリから届いた時刻あわせコマンドの設定値に従う)」という状態で管理されています。
VysorなどからAndroidのタイムゾーンをUTC以外に変更しても、基本アプリをTHETAに接続すると元の状態に戻されます。
基本的にはこのあたりがシビアになることは行わないと思います。弄らずに使用したほうが無難です。

OpenSSHクライアントも使えます

ここまで、設定することが多めなOpenSSHサーバーについて詳しく書きましたが、クライアント動作もできます。
curlコマンドで撮影したら、別マシンで動作しているSFTPサーバーへファイルを書き込むようなプログラムも作れますのでご安心を。
(わかっているとは思いますが、念のため…)

THETA内部でプログラミング

可能性が無限大に広がってしまう話なので、最小限のポイントに絞ります。

以降では、「インストールが必要な事項はCLモードで外部ネットワーク接続」「そうでない場合はAPモードでもOK」ということについて、いちいち記載しませんので各自でその都度判断してください。

git,wgetも使えます

以下二つはインストールしておいたほうが良いです。
特にgitは、GitHubからベースとなるプロジェクト一式を持ってこれるだけでなく、自身の成果物を作業履歴つきでバックアップしたり、公開したりもできて便利です。

apt install git
apt install wget

マルチ言語開発と実行が可能

他にもいろいろつかえるのですが、取り急ぎC,C++コンパイラとpython3をいれましょう。

C,C++のコンパイラはclangです。apt,pkgなどでインストール作業を行うとビルドも自動でなされる場合があるので、Termux環境に必須といっても過言でないかと。以下コマンドでインストールしてください。

apt install clang

インストール後は gcc,cppを打ってもclangが動作するようclangの別名が設定され、外部から取得したmakefileが大抵動作するようになります。

Python3は以下コマンドでインストールしてください。インストール後はpipも使えます。

apt install python

インストールしたあと、バージョン表示をした結果は以下のとおり。

インストール結果.jpg

pythonでwebUIのサンプル

HTTPサーバーが簡単に立つのでPython事例として挙げておきます。

まず flaskというPythonのライブラリをインストールします。

pip install flask

つづいてお好みのディレクトリに以下のコードを書きます。
ブラウザでアクセスしたとき「Hello World!」と表示されるだけのサンプルです。

hello.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_cloud():
       return 'Hello World!'

app.run(host='0.0.0.0')

保存したら以下でHTTPサーバーを起動します。(パスやファイル名はお好みで)
起動するとコマンドプロンプトが戻ってきません。「Ctrl+c」で終了させるとプロンプトが戻ります。

python hello.py

あとは同一ネットワークにいるマシンのブラウザから以下にアクセスします。

http://localhost:5000/

※localhostは、APモードなら「192.168.1.1」CLモードなら「クライアントアプリの設定」の項に出てきた方法で調べてください。

ポート番号を指定していないので5000番になります。8888番を指定すると、通常THETAプラグインのwebUI事例と同じになります。しかし、Termuxビルド時のassetフォルダに「このアプリにはwebUIがあるよ」を示すxmlファイルを置けていませんので、THETA基本アプリからブラウザを起動する振る舞いができない点はご注意ください(Termuxを使うような方は直接入力のほうが楽かと思いますが念のため)。

cat -nでコード表示 → サーバー起動 → 同一ネットワーク上別マシンから表示
をした動作例は以下です。

HTTPサーバー.gif

他のPython簡単事例を作るためのキーワード

サンプルを作る時間がなかったので、THETAで便利そうなキーワードを少々。

  • PycURL(pycurl)を使うと、webAPIを使ったコードが楽にかけると思います。
  • PyDriveをつかうとGoogle Driveアクセスをするコードが楽にかけると思います。
  • NumPyなど当たり前に動くので、姿勢センサー出力を行列演算するコードも楽にかけると思います。

Termux:APIで機能拡張(CUIで姿勢センサーや音再生)

コマンドラインからAndroid固有の機能を使えるようにするTermux:APIの導入方法を紹介しておきます。
最新の情報はTermux:APIのWikiを参照してください。日本語ではこちらの記事が参考になると思います。

沢山のことが行えますが、現時点でTHETAと相性が良いのは以下と思われます。

コマンド名称 できること
termux-sensor 姿勢センサーの情報、主に加速度(3軸)、角速度(3軸)、地磁気(3軸)取得する
termux-media-player 任意の音楽ファイルを再生する

追加機能apkインストール

AndroidのsharedUserIdという仕組みをつかってTermux本体に追加される機能です。
F-Doroidに公開されているTermux:APIの最新apkを取得してインストールしてください。

インストールの仕方はTermux本体のapkインストールと同じです。

Termux本体と同じ署名がされてなければインストールできません。
Termuxに独自の仕掛けを追加するわかりやすい事例にもなっているので、公開されているソースコードをベースに自身でビルドした場合は、Termux本体とTermux:APIの両方に同じ署名をする必要があります。(Google Playが使えるスマートフォンでTermuxを利用するときに、GooglePlayとF-Droidのapkを混在させることができないのと同じ理由です)

Termux内の追加機能インストール

Termuxのシェルから追加機能を呼び出すためのプログラムが必要となります。
Termuxにログインしたら、コマンドラインから以下を入力してインストールしてください。

apt install termux-api

コマンドラインから姿勢センサーを使う

ヘルプを表示すると、オプションが分かります。

$ termux-sensor -h
Usage: termux-sensor
Get information about types of sensors as well as live data
  -h, help           Show this help
  -a, all            Listen to all sensors (WARNING! may have battery impact)
  -c, cleanup        Perform cleanup (release sensor resources)
  -l, list           Show list of available sensors
  -s, sensors [,,,]  Sensors to listen to (can contain just partial name)
  -d, delay [ms]     Delay time in milliseconds before receiving new sensor update
  -n, limit [num]    Number of times to read sensor(s) (default: continuous) (min: 1)
$

-lオプションを使い、このハードウェアで出来ることを確認すると以下です。
1つのセンサーの生データだけでなく、扱いやすく加工したデータを取得できるようです。
結果はJSON形式で得られます。

$ termux-sensor -l
{
  "sensors": [
    "LSM6DSM Accelerometer",
    "AK09915 Magnetometer",
    "AK09915 Magnetometer Uncalibrated",
    "LSM6DSM Gyroscope",
    "LSM6DSM Gyroscope Uncalibrated",
    "LSM6DSM Accelerometer -Wakeup Secondary",
    "AK09915 Magnetometer -Wakeup Secondary",
    "AK09915 Magnetometer Uncalibrated -Wakeup Secondary",
    "LSM6DSM Gyroscope -Wakeup Secondary",
    "LSM6DSM Gyroscope Uncalibrated -Wakeup Secondary",
    "Gravity",
    "Linear Acceleration",
    "Rotation Vector",
    "Step Detector",
    "Step Counter",
    "Significant Motion Detector",
    "Game Rotation Vector",
    "GeoMagnetic Rotation Vector",
    "Orientation",
    "Tilt Detector",
    "Gravity -Wakeup Secondary",
    "Linear Acceleration -Wakeup Secondary",
    "Rotation Vector -Wakeup Secondary",
    "Step Detector -Wakeup Secondary",
    "Step Counter -Wakeup Secondary",
    "Game Rotation Vector -Wakeup Secondary",
    "GeoMagnetic Rotation Vector -Wakeup Secondary",
    "Orientation -Wakeup Secondary",
    "AMD",
    "RMD",
    "Basic Gestures",
    "Facing",
    "Pedometer",
    "Motion Accel",
    "Coarse Motion Classifier"
  ]
}
$

重力加速度を 10msec間隔で取得する場合は以下を打ち込みます。

termux-sensor -s "Gravity" -d 10

こちらもJSON形式で結果が得られます。

姿勢データ取得.gif

コマンドラインで実行した場合には、「Ctrl+c」で終了できます。

コマンドラインから任意の音楽ファイルを再生する

SFTPで外部からファイル書き込みができるようになっていると思いますので、再生したいmp3ファイルをどこかに置いて以下コマンドを実行してみてください。

termux-media-player play <mp3filename>

自然音の音量が小さいのはスピーカー特性によるもので「これまで通り」です。普通に再生できます。
以下記事の音楽ファイルも普通に再生できました。

その他のこのコマンドの使い方は以下でご確認ください。

termux-media-player help

これで、Termux環境で作成するプログラムにも音再生のバリエーションを加えられますね。

惜しくも使えなかったもの

電話をかける、スケジューラーや電話帳の操作をする、各種ポップアップ表示をするというような系統は、明らかにTHETAに不要なのはご理解いただけると思います。

以下については、THETAで使えると便利そうですが、提供されたままの状態では動きませんでした。

No コマンド名称 普通のAndroid機ならできること
1 termux-microphone-record マイクから録音する
2 termux-camera-photo カメラで撮影する
3 termux-usb usb機器と通信できるようにする
4 termux-tts-speak Text To Speechを動作させる

動作しない理由は以下です。
1~3につてはTermux:APIの仕組みに皆さんが手を加えることで動きそうです。

  • 「termux-microphone-record」について
    こちらの記事にある「モノラル音声指定」をTermux環境で行う方法が今時点みつかっていません。
  • 「termux-camera-photo」について
    こちらのドキュメント「Notifying Camera Device Control」に従い、CameraAPIの実行権をTermuxにしたのですが0 Byteのファイルができるだけでした。未調査ですがTermux:APIはCameraAPI2を利用しているのかもしれません。(webAPIが使えますので、このコマンドが使えなくても問題ないとは思います。)
  • 「termux-usb」について
    termux-usbのWikiに記載されたサンプルプログラム動作まではできたのですが… libusbを使ってUSBシリアル通信などを組むには手間がかかりそうです。あと、パーミッションを毎回与えなければならない振る舞いになりました・・・。Linuxらしさは薄れますが、今は他の方法で実現するのが早そうです。
  • 「termux-tts-speak」について
    picoTTSがプリインストールされていることにお気づきの方がいるかもしれません。しかし、製品動作として利用していないため正常動作するものではありません。英語の発話だけですが、プラグイン作成に役立つと思われ、将来動作させたいと考えてはいますが。。。今はお許しを。

その他の拡張や将来性

「TermuxやTermux:APIに手を加えずに利用する」という範疇では、これまでの記事と比較して以下事項ができていません。

  • 本体ボタン操作(=THETAに直接接続したキーボード含む)を受け取る
  • OLEDに画像データを表示する
  • マイクからの音データ利用
  • CameraAPIを利用した高度な映像利用(例えば4K30fpsのライブストリーミングなど)
  • USB OTGで外部機器とシリアル通信する(手間をかければできますが一応記載)

Termux:APIの章で少し触れましたが、こういったTHETA独自のハードウェア構成に依存する事項はTermuxAPIの仕組みを真似することで対応できます。

Androidアプリケーション側のコードとsocket通信で指示をしたりその結果を受け取ったりします。Linuxで対象のハードを使うときの作法を守れないこともあり、Linuxの世界での流用がしにくくなりますが、Termux環境でできないことはないという状況かと思います。

また、機能拡張も行われており

なんてこともあったり、まだ機能追加リクエストレベルですが

なども進みそうです。
なんだか可能性が無限大すぎて怖いレベルです。

まとめ

Termux環境構築にトライすることで、普通のTHETAプラグインの作り方の知識を広くすばやく吸収できたのではないかと思います。

環境構築を終えると各種スクリプトが使えるのが強力です。
「THETAでこれちょっと試したい」ということに直ぐにとりかかれます。最終的に行いたいことの要素を別々に検証したあと、統合動作させることも簡単です。以前に作った要素の使いまわしもしやすいですし、自身が行ったことがないことでもLinux系(特にラズパイ)で実績があれば手数少なく(ネットワーク関係なら大抵はそのまま)移植できる可能性が高いです。

Linuxの心得があるかたなら、Android Studioを立ち上げ apkをビルドし、THETAにインストールするほどのことでもないことがサクサクと行えるようになります。
たとえば、「ブラケットインターバル撮影」「ちょっとした画像処理」「ファイル転送関連もろもろ」「姿勢検出の検証」etcができます。
雛型スクリプトを仕込んでおいて、撮影地でパラメーターだけ少しいじるなんて使い方もありだと思います。

今回の記事は「Termux導入編」といったところでしょうか。いくつか提示した課題解決ができたり、Termux環境のほうが便利と思われることがあったら、たまにはこの系統の続編も書いてみようとおもいます。
皆さんも是非Termux環境を試してみてください。

RICOH THETAプラグインパートナープログラムについて

THETAプラグインをご存じない方はこちらをご覧ください。
パートナープログラムへの登録方法はこちらにもまとめてあります。
興味を持たれた方はTwitterのフォローとTHETAプラグイン開発コミュニティ(Slack)への参加もよろしくおねがいします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[暫定版]富士通FARQ30WRJ/WBJ (Arrows Tab QH30/W)にPeppermint 10を入れてみた

初めに

これは完全に個人的なメモですが、「特定機種向け情報」として公開します。
Peppermint 10はUbuntu 18.04系の派生ディストリビューションで、インストールそのものは一般的なディストリビューションと大差ない筈・・・いくつかの問題点を除けば。
なおこの問題はFedora30 LXDEでも発生していました。

問題点

(32bit UEFI なマシンに amd64向けUbuntuをUSBメモリから起動してインストールする方法は沢山出回ってるので割愛)
- とりあえず画面が左に90度回転してて、タッチパッドの向きと画面表示の向きとが合ってない
- とりあえず画面表示の向きはxrandr, もしくはarandrで修正できます。
- xrandr, arandr で修正したらタッチパッドの向きは合ったけど、今度はタッチスクリーンが何かおかしい
- 別途 xinput で修正しなければならない

画面表示の向きとタッチスクリーンの向き、それからタッチパッドの向きを整理する

FARQ30WRJ_X11.png

解決策

とりあえず、rotate_screen.shFARQ30WRJ向け修正版を$PATHが通った場所に置いて、ログイン時に自動実行するように設定し、画面向きとタッチスクリーンのタッチ位置を合わせた。

推測される原因

おそらくハードウェア側がこういう仕様になってる。UEFIの設定画面ですら画面向きとキーボードの上下左右キーの向きが合ってない。
なのでWayland + libinputでも発生すると思う。
本来ならxorg.confで修正すべき事なので、タイトルには[暫定版]と入れている。

最後に

ぶっちゃけ画面の自動回転って要らないよね?と思うので、他環境を使用する時の為に、自動回転の止め方を書いておく。

$ sudo systemctl stop iio-sensor-proxy.service
$ sudo systemctl disable iio-sensor-proxy.service

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

簡単だけど注意しておきたいSplunkインストール前の考慮点

本記事は、Splunk Advent Calendar 2019 の2日目の内容になります。

はじめに

普段、主に業務でSplunkを0からインストールし各種設定を行うことを対応しております石橋と申します。よろしくお願いします。
Splunk歴は浅いですが、これまで様々なOS/構成のSplunk構築業務を行ってきましたので、それらから得たコトよりSplunkをインストールする時の考慮点などを共有したいと思います。
ちょっくらSplunkを使ってみっかと考えている人の参考になれば幸いです。

Splunkはインストールだけなら超簡単

いきなり自分の仕事を否定するようなことを書きますが、Splunkは「いったん手持ちのデータを分析できるようにする」だけなら、すぐに使うことができます。

Splunk外のモジュールやライブラリを予めインストールしておくことは基本的にはなく、カーネルパラメータや環境変数の設定などといったOS環境に関わる変更も事前にすることはあまりないため※1、アンインストールも特に苦労はせず実施できます。製品評価を行う点において、検証環境にサクッと入れて評価後はサクッと消すことが簡単に出来るのはSplunkの一つのメリットではないかと思います。

※1.LinuxOSにインストールする場合はSplunk起動ユーザやリソース割り当てに関する考慮が必要です(後述)

設定変更も難しくはない(Splunkだけなら)

Splunkの設定方法は、大きく分けて3種類あります。

  1. GUI(Splunk管理画面)で変更する。
  2. CLI(splunkコマンド)で変更する。
  3. 設定ファイルの内容を変更する。

それぞれメリット/デメリットがありますが、どの方法でも最終的に設定ファイルに設定パラメータが記録されます。Splunkは仕様上さまざまな設定ファイルを持っていますが、設定パラメータはいずれかの設定ファイルに残るようになっています。よって、Splunkをまずはデフォルト設定でインストールし、後から設定を変更することはあまり難しいことではありません。
そう、Splunkのことだけならね。

本題

ようやく本題ですが、Splunkを何らかのシステムの一つとして使う場合に気を付けるポイントについて説明します。

  1. インストールパス(SPLUNK_HOME)
  2. データ保存パス(SPLUNK_DB)
  3. Splunkプロセス起動ユーザー
  4. 通信ポート
  5. NTP
  6. 自動起動設定(主にUnix版)

1.インストールパス(SPLUNK_HOME)

Windows版Splunkインストーラは、インストーラー実行時にインストールパスを指定できます。デフォルトではC:\Program Files\Splunkが指定されます。一方Unix版はrpmパッケージでインストールした場合とtar.gzファイルを展開した場合とでインストールパスが異なります。

  1. rpmパッケージでインストールした場合・・・デフォルトでは/opt/splunkにインストールされ、自動でOSにsplunkユーザーが生成されます。(uid,gidは1001のようです) なお、インストールパスを変更する場合は、rpmのコマンドオプションに--prefix=<Install Path>を指定することで任意のパスに変更することができます。

  2. tar.gzファイルを展開した場合・・・tarの-Cオプションを指定しない限り、tar.gzがあるパスにsplunkディレクトリが生成され、その中に実行モジュールが一式展開されます。(中身のuid,gidは10777のようです。)

なお、マニュアルではUnix版のインストールパスは/opt/splunkで統一されているようです。また、マニュアルやREADMEではインストールパスのことを$SPLUNK_HOMEというキーワードで説明されていたりしますが、環境変数の設定は不要です。

2.データ保存パス(SPLUNK_DB)

Splunkに取り込んだデータは、デフォルトではSplunkインストール先と同じパスに保存されます。
インストール先はOSによって異なります。

Host OS Data Path Default Path
Linux <Install Path>/var/lib/splunk /opt/splunk/var/lib/splunk
Windows <Install Path>\var\lib\splunk C:\Program Files\Splunk\var\lib\splunk

データ保存先をデフォルト設定から変える場合、以下の設定ファイルにパラメータを絶対パスとして設定します。
※設定を変更した後はSplunkプロセスの再起動が必要です。

Configuration File Parameter Name Default Value
<Install Path>/etc/splunk-launch.conf SPLUNK_DB <Install Path>/var/lib/splunk

なお、データ保存パスを変更しても、パス変更前のデータは変更後のパスに自動で移動しませんし、変更前パスの削除もされません。このため「パス変更前のデータを変更後もSplunkでサーチできるようにしたい」といった要件がある場合、過去データの移行について検討する必要がでてきます。

また、データ取り込み量の増加やデータ保管期間の変更などによって、ディスク領域を増やす必要が出てきた場合、データ保存先がシステム領域と同じパーティションかそうでないかによって検討事項などが変わってくることが想定されます。

インストール前の段階でSplunk導入後のデータ量について検討しておき、その検討結果に従ってデータ保存先パスをデフォルトのままとするのか考慮するのが望ましいと思います。

※NFSについて

データ保存パスをNFSにする場合、インデックスのパフォーマンスに悪影響が出る可能性があることを考慮するようマニュアルに記載されてます。また、マニュアルにはホットバケツやウォームバケツのパスとしてNFSを割りててはいけないと記載されています。

しかし、SPLUNK_DBで指定するパスについてバケツ単位での指定は出来ないため、事実上SPLUNK_DBにNFSのパスを指定することは不可能で、あるインデックスのコールド/フローズンのバケツのパスのみNFSを指定することが(設定的には)可能ということになります。

※参考
Considerations regarding Network File System (NFS)

※CIFS/SMBについて

データ保存パスをCIFS/SMBにする場合については、一部のバケツ(コールド/フローズン)では使える旨がマニュアルに記載されています。こちらについてもNFS同様に事実上SPLUNK_DBではCIFSのパスを指定することは不可能です。

※参考
Considerations regarding Common Internet File System (CIFS)/Server Message Block (SMB)

3.Splunkプロセス起動ユーザー

Splunkはプロセス起動ユーザーが特権ユーザー(いわゆるrootやAdministrator)か非特権ユーザーによって動作が変わることはありません。非特権ユーザーでもインストールパスおよびデータ保存先に適切なパーミッションが設定されていれば実行することができます。
一方、Splunkにデータを自動で取り込めるようにする場合において、起動ユーザーが深く関係してきます。"自動で取り込めるようにする"とは、例えば以下のようなシチュエーションです。

    • サーバーやアプリケーションが出力するログファイル(例:/var/log/messages)をSplunkに継続的に取り込めるようにしたい。
    • スクリプトの実行結果を毎分Splunkに継続的に取り込めるようにしたい。
    • あるディレクトリ(例:/tmp/upload)にファイルを置いたら、そのファイルをSplunkに自動で取り込めるようにしたい。

上記を実現するための前提条件として「Splunk起動ユーザーに適切なパーミッションが適用されていること」があります。つまり、ファイルを取り込むためにはSplunk起動ユーザーにファイルの読取権限が要りますし、スクリプトの実行結果を取り込むにはSplunk起動ユーザーにスクリプトの実行権限が要ります。

Splunkの起動ユーザーを特権ユーザーにすればパーミッションを意識する必要は殆どなくなりますが、システムのセキュリティ要件などで、プロセスの起動ユーザーに特権ユーザーが認められない場合、取り込み対象のファイル/実行スクリプトのパーミッションに注意が必要です。

注意が必要な例:
Splunkのプロセス起動ユーザーは非特権ユーザー(root以外)とし、
OSのシステムログ(/var/log/messages,Windowsイベントログ(システム))を取り込む設計とする。
→ システムログは通常特権ユーザーしか読取権限がない。OMG。
→ システムログのパーミッションを変える?システムログの内容を別ファイルに出力してそっちを読み取るようにする?
→ 起動ユーザの権限をどげんかする?

・・・というような課題がでてくることに注意が必要です。
また、Splunkはデータ取り込み対象だけではなくSpunkが参照するファイルにも起動ユーザーのパーミッションが必要です。よって、プロセス起動ユーザーを後から別ユーザーに変更する場合は、インストール先パスおよびデータ保存先パスのファイル/ディレクトリのパーミッションも変更する必要があります。

なお、Splunk社は特権ユーザーでのプロセス起動を非推奨とし、Splunkの起動には専用アカウントを作ることを推奨としているようです。

4.通信ポート

SplunkはTCPのポートを複数使用します。このポートはインストール後も設定変更できます。しかし、通信ポートを後から変更する場合、ファイアウォールやロードバランサーなどSplunk外の機器の設定などにも影響する可能性があるため、可能であればインストール前に通信要件を十分考慮しておく必要があります。

以下に代表的なポートをご紹介します。
※デフォルト設定ファイルは<Install Path>/etc/system/default/に保存されています。

No Purpose Default No(TCP) Configuration File Stanza Attribute misc
1 Splunk管理通信用 8089 web.conf [settings] mgmtHostPort Splunkのほとんどの管理通信で使われる超重要なポート。
2 Splunk管理画面用 8000 web.conf [settings] httpport Splunkのweb画面のアクセス先ポート。
3 Web app-server proxy 8065 web.conf [settings] appServerPorts 内部通信で使われるポート。
4 KV store Port 8191 server.conf [kvstore] port 内部通信で使われるポート。

通信ポートが既に使われていた場合の注意

CLIでSplunkを起動した時に、Splunkが使う通信ポートが既に別プロセスに使われていた場合、警告プロンプトが表示され、別のポートに変更するか起動処理を停止するか選ぶことができます。よって、Linux版Splunkは初回起動時に、(最悪)ポートが別プロセスに使われているか知ることができます。

一方、Windows版Splunkインストーラは、インストールが正常終了するとSplunkが自動で起動するのですが、Splunkの通信ポートが別サービスで使われていた場合、自動で別ポートを割り当ててしまいます。(8089ポートが既に使われていると8090をSplunk管理ポートとして使うよう設定してしまう。)この時、警告ウィザード等一切出ないため、通信要件が不明確の場合は特にSplunkのポートが使われていないか注意する必要があります。

その他の通信ポート

その他、デフォルト値が明示されていないSplunkが使用する主な通信ポートについてご紹介します。

No Purpose Description
1 データ受信用ポート Splunkが他のSplunk(Universal Forwarder含む)からデータを受信するためのポート。マニュアルやweb画面などでは9997が指定されている。
2 ネットワークデータ受信用ポート syslogなどでデータを受信するためのポート。1ポート=1ソースタイプになる。
3 レプリケーション用ポート Splunkのクラスタリング構成(インデクサークラスター,サーチヘッドクラスター)においてSplunk間で使用するポート。マニュアルやweb画面などでは8080が指定されている。
4 HEC 通信用ポート SplunkでHECを使った場合にデータを受信するためのポート。マニュアルやweb画面などでは8088が指定されている。

Splunkのプロセス起動ユーザーを非特権ユーザーにする場合は、well-known-port(1024未満のポート)が使えないため、非特権ユーザーで通信ポートをデフォルトから変える場合は注意が必要です。

5.NTP

データを取り込んだときのタイムスタンプのズレを極力なくすため、SplunkサーバーはNTPサーバーと同期させておくのが望ましいです。

6.自動起動設定について

OSの起動/停止に合わせてSplunkの起動/停止を制御する場合、OSによって設定が異なります。

WindowsOSの場合

Splunkのインストール時にデフォルトでOSの起動/停止に合わせてSplunkが起動/停止するよう、Windowsサービスに登録されるため、通常は特に設定する必要はありません。

UnixOS(MaxOS含む)の場合

UnixOSの場合、Splunkインストール後に自動起動設定を行います。この際に考慮が必要なのが「systemd/sysVinit(initd)のどちらの起動方式を採用するのか」「どのユーザーでプロセスを自動起動させるのか」です。

systemd/sysVinit(initd)のどちらの起動方式を採用するのか

Splunkは自動起動を設定するCLIコマンドとしてsplunk enable boot-startというコマンドが用意されています。このコマンドを実行すると、OSの起動/停止に合わせてSplunkが起動/停止するように、OSに起動スクリプトが生成されます。

また、Splunkはバージョン7.2.2よりsystemdによる起動がサポートされました。
上記のCLIコマンドsplunk enable boot-startを実行する時に、オプション-systemd-managed 1を指定することで、systemd起動の設定が行われます。
ここで、オプションを省略した場合、Splunkバージョンによって設定される起動方式が変わるので注意が必要です。

Version -systemd-managed 1 オプション省略時に設定される起動方式
~7.2.1 指定不可(オプションを指定するとエラーになります)
7.2.2 systemd起動
7.3.x~ sysVinit(init)起動
8.0.0※ sysVinit(init)起動

※2019/12/2時点の最新バージョン

なお、起動方式や起動ユーザーによって起動中のプロセスの引数が変わるようです。この点はSplunkプロセスの起動状態をSplunk外のプロダクトで監視する場合に考慮が必要です。

psコマンド結果例
#sysVinit(init)起動の場合
root      3525     1 18 08:16 ?        00:00:01 splunkd -p 8089 start

#systemd起動の場合
root      3016     1 26 08:15 ?        00:00:01 splunkd --under-systemd --systemd-delegate=yes -p 8089 _internal_launch_under_systemd

どのユーザーでプロセスを自動起動させるのか

自動起動設定コマンドsplunk enable boot-startに、オプション-user <user_name>を指定することでOS起動時に自動起動するSplunkのプロセス起動ユーザーを指定できます。
オプションを省略した場合はrootで起動します。

ここで注意が必要なのが"sysVinit(init)起動"かつ"プロセス起動ユーザーが非特権ユーザー"の場合で、splunk enable boot-startコマンドを実行した後に手動で起動スクリプトを書き換える必要があります。

具体的には/etc/init.d/splunkファイルに記載されているプロセス起動コマンドについて
非特権ユーザーで起動するよう修正します。

「-userオプションをつければOK!」と思いがちなので要注意です。

sysVinit(init)起動の場合の追記(/etc/init.d/splunk)
# 変更前
splunk_start() {
  echo Starting Splunk...
  "$SPLUNK_HOME/bin/splunk" start --no-prompt --answer-yes
(中略)
splunk_restart() {
  echo Restarting Splunk...
  "$SPLUNK_HOME/bin/splunk" restart
(後略)

# 変更後
USER=splunk # 追記
splunk_start() {
  echo Starting Splunk...
  su - ${USER} -c '"$SPLUNK_HOME/bin/splunk" start --no-prompt --answer-yes' # 修正
(中略)
splunk_restart() {
  echo Restarting Splunk...
  su - ${USER} -c '"$SPLUNK_HOME/bin/splunk" restart' # 修正
(後略)

※参考
Enable boot-start as a non-root user

リソース設定 ※Linux版のみ

Splunkは実行中に多くのOSリソースを消費するため、マニュアルにOSのulimitコマンドを使ったリソース割当設定が記載されています。

System-wide Resource ulimit invocation Recommended min. value
Open files ulimit -n 64000
User processes ulimit -u 16000
Data segment size ulimit -d 1073741824

ここで、OSの起動に合わせてSplunkが自動起動するように設定する場合、起動したプロセスに適切なリソースを割り当てるため、自動起動スクリプトにリソース設定の追記が必要になります。
なお、CLIによるオプションが用意されていないため、手動で設定ファイルを修正します。

また、sysVinit(init)起動方式において、Splunkをインストールパスから直接起動する場合(<Install Path>/bin/splunkを直接実行する場合)は、/etc/init.d/splunkに設定したulimit値が適用されないため、実行前にulimitコマンドを実行するか、/etc/security/limits.confに、PAM認証を通ったユーザーへのリソース設定を入れておくことで、リソース割り当てを直接起動するSplunkプロセスに適用することができます。

/etc/security/limits.confのリソース設定例
    *       soft    nofile      64000
    *       hard    nofile      64000
    *       soft    noproc      16000
    *       hard    noproc      16000

※参考
Considerations regarding system-wide resource limits on *nix systems

I get errors about ulimit in splunkd.log

THP設定 ※Linux版のみ

LinuxでSplunkを動かす場合、THPと呼ばれるOSの機能を無効化するようマニュアルに記述されています。
ここでOSの起動に合わせてSplunkが自動起動する場合にTHP機能を無効化するために、リソース設定同様、自動スクリプトに追記が必要になります。

※参考
Transparent huge memory pages and Splunk performance

systemd起動方式時の特殊設定 ※Linux版(7.2.2~7.3.x)のみ

起動方式をsystemdにした場合、systemdのサービス停止時の仕様上、プロセスに強制終了(SIGTERM)シグナルを送るのがデフォルトの動作のようです。
強制終了にさせたくない場合はSplunkdのunitファイル(デフォルトでは/etc/systemd/system/Splunkd.service)に以下の設定を追加します。

KillMode=mixed
KillSignal=SIGINT

なおSplunkバージョン8.0.0では、自動起動設定時に自動的にこの設定が入るようです。

※参考
https://answers.splunk.com/answers/735189/splunk%E3%82%92systemd%E3%82%B5%E3%83%BC%E3%83%92%E3%82%B9%E3%81%A8%E3%81%97%E3%81%A6%E5%81%9C%E6%AD%A2%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AE%E5%95%8F%E9%A1%8C%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html

起動スクリプトの修正例

以上のリソース設定およびTHP設定をふまえた自動起動スクリプトの例をinitd/systemdそれぞれご紹介いたします。
※設定値は導入サーバーのOSにあわせて適宜変更してください。

init.d起動の場合の修正例(/etc/init.d/splunk)
splunk_start() {
  if test -f /sys/kernel/mm/transparent_hugepage/enabled; then echo never > /sys/kernel/mm/transparent_hugepage/enabled # 追記
  fi # 追記
  if test -f /sys/kernel/mm/transparent_hugepage/defrag; then echo never > /sys/kernel/mm/transparent_hugepage/defrag # 追記
  fi # 追記
  ulimit -n 64000 # 追記
  ulimit -u 16000 # 追記
  ulimit -d 1073741824 # 追記
  echo Starting Splunk...
  su - ${USER} -c '"$SPLUNK_HOME/bin/splunk" start --no-prompt --answer-yes' # 修正

}
(中略)

splunk_restart() {
  if test -f /sys/kernel/mm/transparent_hugepage/enabled; then echo never > /sys/kernel/mm/transparent_hugepage/enabled # 追記
  fi # 追記
  if test -f /sys/kernel/mm/transparent_hugepage/defrag; then echo never > /sys/kernel/mm/transparent_hugepage/defrag # 追記
  fi # 追記
  ulimit -n 64000 # 追記
  ulimit -u 16000 # 追記
  ulimit -d 1073741824 # 追記
  echo Restarting Splunk...
  su - ${USER} -c '"$SPLUNK_HOME/bin/splunk" restart' # 修正
  RETVAL=$?
  [ $RETVAL -eq 0 ] && touch /var/lock/subsys/splunk
}
systemd起動の場合の追記(/etc/systemd/system/Splunkd.service)
(中略)
[Service]
Type=simple
Restart=always
ExecStartPre=/bin/bash -c "echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled && echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag" # 追記
ExecStart=/opt/splunk/bin/splunk _internal_launch_under_systemd
KillMode=mixed # 追記
KillSignal=SIGINT # 追記
TimeoutStopSec=360
LimitNPROC=16000 # 追記
LimitNOFILE=65536
SuccessExitStatus=51 52
RestartPreventExitStatus=51
RestartForceExitStatus=52
Delegate=true
CPUShares=1024
MemoryLimit=1031450624

おわりに

はじめに書きましたがSplunkの設定変更自体はあまり難しい作業ではありません。
設定値を決め、設定変更し、設定を適用して終わり。シンプルな流れです。

では、上記で挙げたことを全て気を付けて設定すればどんな環境でも大丈夫!・・・かというと、そうではなく、環境によって注意しなければならないことは環境により他にも様々あることが考えられます。(独自サーバー証明書が要るとか、LDAP認証をするとか)

ポイントは、後から変更することが容易なこと/後から変えることが大変なことを、予め想定したうえで設計を進めてくことが導入時/導入後のトラブルを防ぐうえで大事ではないかと思います。
ありがとうございました。

補足

Splunkはインストール時にOSの環境変数を設定しません。また、実行バイナリは/bin/配下に保存されています。よって、本文中に記載しているCLIコマンドを実行するためには、実行バイナリのディレクトリでコマンドを実行するか、コマンドパスを通しておく必要があるのでご注意ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSLでLinuxライクにターミナルで遊ぼう(前編)

※本投稿はcommew Advent Calendar 2019の1日目の記事です。

はじめに

こみゅーはWeb系フリーランスのコミュニティーなだけに、たまーにPC買い換えたりするタイミングで

 「WindowsとMacだったらどっち買うべきでしょうか?」

という質問が出たり、

 「Docker扱いづらいから早くMac欲しいなー」

って声が上がったりします。

「Web開発ならMac」って意見がやっぱり多いし実際Mac使いのメンバーが多数派な印象なんですが、やっぱりMacはUnix互換のOSだけあって、iTerm2みたいな優秀なターミナル上ですぐに使えるshellがあったり、デフォルトでRubyやPythonといったプログラミング言語がインストールされてWebサーバー上で動く環境と揃えやすく親和性が高い故にすんなり開発に取り組めるんじゃないかなってのは、使った事がない僕1でも同意します笑2

でも最近のWindows上のLinux環境の急速な進化で、その差もどんどん少なくなってきている様ですよ!
WindowsPCはハードが性能の割に安価なのと、メモリ増設等のカスタマイズが容易にできるというメリットもありますしね。
あとはゲームがしやすいとか笑3

Windows上のUnix互換環境について

Windowsにも随意分前(1995年位)から Cygwin というUNIXライクな環境を提供する互換レイヤーや、MSYS2(MinGW)といったGNUツールチェーンの移植版があります。要はこれらは貧弱なコマンドラインしかなかったWindowsを何とかLinuxの使い勝手に近づけようってプロダクトであり、僕も随分とお世話になりましたが、やはりそれなりに使える環境にするにはかなりの手間と時間が必要です。

しかしWindows10になってからは、WSL(Windows Subsystem for Linux)という仕組みが標準でOSに組み込まれる様になり、Linuxライクどころか本物のLinuxディストリビューションが手軽に使える様になりました。
これを使いやすいターミナルエミュレータと組み合わせる事でLinuxのCLI環境が手に入り、bashやzshといったシェルを操りWindowsの全てのファイルにアクセス可能で、LinuxのシェルからWindowsのプログラムを起動する事も出来る様になります。

WSLでできないこと

現状のWSL(WSL1)は、Linuxそのものではなく、LinuxカーネルへのシステムコールをWindowsカーネルの機能に変換して実行しています。なのでホストOSのLinuxカーネルを共有する仕組みで動作するDockerの様なコンテナは直接使う事が出来ません。
2020年5月以降にリリース予定の「20H1」というWindows10のバージョンではWSL2が採用される事になっています(Insider Preview版のWindows10では既に試せる)が、こちらでは本物のLinuxカーネルがWindowsに載るので、Dockerもかなり簡単に扱える様になります。4
WSL1からWSL2には環境そのままコマンド1発でとても簡単に変換出来るので、Windows10の一般ユーザーである私たちはWSL2のリリースまで以下で紹介する手順で環境を整えておくとしましょう!

Windows10へのWSLの導入

1. WSL機能を有効にする

  • 「スタート」をクリックし、表示されたアプリの一覧の「W」欄から「Windowsシステムツール」をクリックします。
    表示された一覧から「コントロールパネル」をクリックします。
    wsl01.png

  • 「プログラム」をクリックします。
    wsl02.png

  • プログラムと機能を選択し、左の「Windowsの機能の有効化または無効化」をクリック
    wsl03.png

  • 「Windows Subsystem for Linux」にチェックを入れて、[OK]をクリック
    *wsl04.png

  • Windowsを再起動する。

以上でWSLの導入は完了です!

2. Linuxディストリビューションのインストール

  • 「スタート」をクリックし、表示されたアプリの一覧の「M」欄から「Microsoft Store」をクリックし、表示されたウィンドウの検索欄に”WSL"と入力してクリックします
    wsl05.png

  • WSLにインストール可能なLinuxディストリビューションが一覧表示されます。いくつか種類があって(確かArchやKali Linuxもあった様な。。)迷いますが、Web上の情報も多い「Ubuntu」を選択する事でクリックします(最新のUbuntuが入ります)。
    wsl06.png

  • 「入手」をクリックするとインストール開始です。
    wsl07.png

  • コマンドプロンプトが起動し、下記の様なメッセージが表示されて止まります。

Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username:
  • WSLで使うユーザー名、パスワード、パスワード(再入力)の順に1行ずつ入力し、[Enter]を押していきます。このあたりGUIなしで普通のLinuxをインストールした場合と一緒ですね。
Enter new UNIX username: rattcv
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
  • 下記の様なメッセージが表示されればUbuntuのインストールは成功です!
Installation successful!
To run a command as administrator (user "root"), use "sudo <command></command>".
See "man sudo_root" for details.

rattcv@MyComputer:~$
  • exitと入力するとコマンドラインが終了します。これでUbuntuが導入されました!

3. ターミナルエミュレータのインストール

この段階でスタートメニューに「Ubuntu」が追加されていて、また画面下部のタスクバーにもUbuntuのアイコンが表示されてクリックすればすぐにUbuntuが使える様になっていますが、これで起動するCLI環境は、Windows標準のコマンドプロンプト上で動きます。日本語入力も出来てこのままでも十分使えますが、CLIアプリケーション上で記号や絵文字等の表示が崩れる問題があります。MacのiTerm2とも遜色無い環境が使いたいので、MS謹製の「WindowsTerminal」がちゃんと使える様になるまでは是非サードパーティーのターミナルエミュレータを導入してみましょう。
mintty という前述した Cygwin 上で使えるWindowsネイティブ(Cygwin用のX Window System無しで使える)な強力なターミナルエミュレータがありますが、ありがたいことにその開発元で wsltty というWSL環境でも直ぐに使える仕組みを準備してくれています。
細かな設定が可能でとても使い勝手が良く、WSL1で使うターミナルエミュレータの中では最もおすすめです。Sixel Graphicsにも対応しているので、ターミナル画面上に画像を表示したり動画を再生する事も可能です(これが滅茶苦茶面白い)。

こちら からダウンロードします。現時点(2019/12/01)では3.0.6が最新で、これはWSL2にも対応しているんですが、前述したSixel Graphicsが正常に動作しないので3.0.2.3をインストールしましょう(画像表示とか必要ない人は3.0.6でOKです)。
この問題は将来の版で解決されるとは思います。(既にリポジトリには3.1.0が上がっていますが自分でCygwinを入れてビルドする必要がある)。

ダウンロードが完了したらファイルクリックでインストールです。インストールが完了するとタスクバーにペンギンのアイコンが追加されるので、これをクリックするとMinTTYでUbuntuが使える様になります。

初期表示はこんな感じで黒画面ですが、設定を変える為にウインドウ上で右クリックして「Options...」をクリックしましょう。
wsl08.png

自分の今の設定はこんな感じです。
wsl09.png

フォントは Cicaフォント がおすすめです。絵文字・アイコン表示もできますしプログラミングにとても適したフォントだと思います。

ここで変更した設定は
C:\Users\%USERNAME%\AppData\Roaming\wsltty\config
に保存されますが、これは直接エディタで編集する事も出来ます。

自分のwslttyの見た目(Vimが起動してます)はこんな感じです。

wsl10.png

参考までに上記画面のconfigを貼っておきますね。

\Users\%USERNAME%\AppData\Roaming\wsltty\config
# To use common configuration in %APPDATA%\mintty, simply remove this file
Locale=ja_JP
Font=Cica
FontHeight=12
ThemeFile=
CursorType=block
CursorBlinks=no
Term=xterm-256color

RowSpacing=2
BoldAsFont=no
FontHeight=12
CursorType=block
CursorBlinks=no
Locale=ja_JP
Charset=UTF-8
Columns=112
Rows=34
ForegroundColour=68,68,68
BackgroundColour=223,223,223
CursorColour=95,135,175
Black=68,68,68
Red=175,0,0
Green=0,135,0
Yellow=175,95,0
Blue=0,95,175
Magenta=135,0,135
Cyan=0,135,135
White=255,255,255
BoldBlack=68,68,68
BoldRed=175,0,0
BoldGreen=0,135,0
BoldYellow=175,95,0
BoldBlue=0,95,175
BoldMagenta=135,0,135
BoldCyan=0,135,135
BoldWhite=255,255,255
Language=ja
BellType=0

ここまでの手順で、ワンクリックでLinuxのCLIが使える環境を整備する事が出来ました。
色々コマンドを打ったり、普通のUbuntu同様 apt でツールをインストールしてみてください!

「後編」では、WebのCLI開発でも良く使う Vim や tmux の、WSL 特有の便利な設定等を紹介したいと思います。ではでは。


  1. ちなみに僕は基本 LinuxDesktop で開発しますが、アプリ作成でWindows使う事もあるためshellが無いと死にます笑 

  2. 最近Webに興味持ち始めた娘向けには MacBook Air のゴールドを購入しました。何かオシャレだし笑 

  3. 反対にiOSアプリはMacじゃないと作れないとか、どうしてもMacが必要なシチュエーションはあると思います。 

  4. 他にも制限はいくつかありますが、今回はDockerを例にあげました。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux perfで快適に計測するためのtips

Linux Advent Calendar 2019 四日目の記事です。Linux perfの使い方は知ってるけど割と不便に感じることがあるのを解消したいという人を対象読者にしています。

なお、perfに元々興味があるけどmanを見てもどう使うのかイマイチわからない、という人は 僕が最初に読んだ記事 … はいつのまにか消えていたので、Brenden Gregg先生のサイト (今見ると、この記事の内容も大体カバーされていますね) に行くか、日本語で読みたい人は詳解システム・パフォーマンスを読んでも概要はわかりそうです。

1. libc6-dbgを入れる

デバッグ対象のプログラムをデバッグシンボル付きでコンパイルしておかないと困るのはまあ当然ですが、そうしていてもlibcなどで未解決のシンボルが登場してしまい、関数名がわからないことがあります。

   0.23%  ruby     libc-2.27.so        [.] 0x00000000000950dd

知っていると割と当然に感じますが、 sudo apt install libc6-dbg などでlibc6-dbgというパッケージを入れるとlibcのシンボルも解決できるようになります。

   1.11%  ruby     libc-2.27.so        [.] _int_malloc

これがあるのとないのとでは分かりやすさが全然違うので、perfを使う時は常に入れておくようにすると便利です。

2. --call-graph は fp 以外で使う

上記の問題を解決すると perf record + perf report では何が呼ばれているかおおむね分かることが多いのですが、call graphを出すために perf record -g をすると [unknown] というのが出てきてしまうことがあります。(以降の計測結果はRack::Utils::HeaderHashを使ったRuby VMのベンチRubyのmasterで走らせたものです)

Samples: 38K of event 'cycles:ppp', Event count (approx.): 271180000
  Children      Self  Command  Shared Object      Symbol
-   15.64%     0.00%  ruby     [unknown]          [.] 0000000000000000
   - 0
        2.20% gc_mark_ptr
        1.73% gc_mark_children
        1.33% vm_call_cfunc
        1.29% gc_aging
        1.26% rgengc_check_relation.part.95
        1.04% vm_exec_core
        0.84% 0x20000
        0.72% gc_sweep_step
+   13.76%    13.43%  ruby     ruby               [.] rb_st_lookup
+   11.82%    11.73%  ruby     ruby               [.] vm_exec_core
-   10.98%     0.00%  ruby     [unknown]          [.] 0x0000555555bcf598
   - 0x555555bcf598
        1.57% rb_memhash
        1.30% rb_str_downcase
        0.62% ar_update
        0.56% rb_hash_aref
        0.53% rb_hash_default_value
+    6.58%     6.42%  ruby     ruby               [.] rgengc_check_relation.part.95
-    5.14%     0.00%  ruby     [unknown]          [.] 0x00000000000015c0
   - 0x15c0
        2.09% vm_call_cfunc
        1.02% vm_exec_core

いやあ、shared objectが [unknown] になってしまうと訳がわかりませんね。
/proc/$pid/map を見ても 0x0000555555bcf598 は [heap] のところにいたりとか、gdbでx/iしても単に 0000... な時の命令が出てるだけとか、そもそも 0000000000000000 が呼び出されるて何やねんとか。

[unknown] 問題に対するBrenden Gregg氏のコメントでは、例えばJavaだと-XX:+PreserveFramePointerをつけ、jvm-profiling-tools/perf-mapagentも利用する必要があるとしていて、アプリごとにどうにかしていく必要がある感じがしています。
じゃあ、と思ってGCCの-fno-omit-frame-pointerをいれてみても、0000000000000000は消えても、他のところでよくわからないアドレスが残ったりしました。

この問題は、私の環境では --call-graph に渡すオプションを、デフォルトの fp (frame pointer) ではなく dwarf や lbr にすることで解決しました。

--call-graph dwarf

このオプションでは、frame pointerがないような状況でもlibunwindがdwarfを使ってfpをunwindしてくれるため、上記の問題を解決してくれることがあるのに加え、本来インライン化されてフレームが存在しないような関数の情報も見ることができます。

Samples: 35K of event 'cycles:ppp', Event count (approx.): 246764000
  Children      Self  Command  Shared Object       Symbol
-   85.75%    10.77%  ruby     ruby                [.] vm_exec_core
   - 74.98% vm_exec_core
      - 63.48% vm_sendish (inlined)
         - 40.67% vm_call_method
            - 40.32% vm_call_cfunc
               - 40.11% vm_call_cfunc_with_frame (inlined)
                  + 31.27% enum_collect
                  + 8.14% rb_hash_aset
         - 20.99% vm_call_cfunc
            - 20.56% vm_call_cfunc_with_frame (inlined)
               + 18.54% rb_str_downcase
                 0.56% rb_str_freeze
           1.19% vm_search_super_method
      + 4.28% vm_opt_aset (inlined)
      + 3.89% vm_getinstancevariable (inlined)
      + 3.27% vm_opt_aref (inlined)
   - 10.22% _start
        __libc_start_main
        main
        ruby_run_node
        rb_ec_exec_node
        rb_vm_exec
      + vm_exec_core
-   85.29%     0.43%  ruby     ruby                [.] rb_vm_exec
     84.87% rb_vm_exec
      + vm_exec_core
+   85.20%     0.00%  ruby     ruby                [.] _start
+   85.20%     0.00%  ruby     libc-2.27.so        [.] __libc_start_main
+   85.20%     0.00%  ruby     ruby                [.] main

VM本体の処理である vm_exec_core にかかる時間85.75%のうち、enum_collect で実装されたメソッド本体に31.27%、rb_str_downcase は 18.54%、Hashに値をセットする vm_opt_aset には 4.28%、インスタンス変数の取得 vm_getinstancevariable は3.87% かかっていた、ということがわかります。このうちいくつかはinlinedであり、本来VM本体の vm_exec_core 単体として出てきてしまうはずのものであるにも関わらず、です。これを見たらVMのどのあたりを最適化すべきか、というのがなんとなくわかりますね。

上記の -g のグラフと計測しているものは同じなのですが、正しく集計できるようになったからか、それぞれの関数が占める割合も全然違うものになっています。

一方、次に述べるlbrに比べると、Dwarf2 unwinding also does not always work and is extremely slow (upto 20% overhead) という欠点があるようです。

--call-graph lbr

lbrはHaswellのLast Branch Recordを使ってcall chainを保存するオプションです。この機能が有効になると、on-chipなLBRレジスタを使ってcallgraphを保存しようとするため、frame pointerに依存しなくとも軽量にcallgraphを保存することができるようです。

これを使うと、同じものを計測した時以下のような出力になります。

Samples: 68K of event 'cycles:ppp', Event count (approx.): 476567000
  Children      Self  Command  Shared Object      Symbol
-   95.02%    10.94%  ruby     ruby               [.] vm_exec_core
   - 86.37% vm_exec_core
      - 40.20% vm_call_cfunc
         + 33.48% rb_str_downcase
           1.73% call_cfunc_m1
         + 0.69% rb_str_freeze
           0.51% CALLER_SETUP_ARG
           0.51% call_cfunc_0
      - 18.34% vm_call_method
         - 16.66% vm_call_cfunc
            + 8.18% rb_hash_aset
            + 7.04% rb_class_s_new
              1.07% call_cfunc_2
           1.68% vm_call_method_each_type
      + 6.66% rb_hash_aset
      + 4.95% rb_hash_aref
        4.54% rb_st_lookup
      + 4.16% rb_hash_new_with_size
      + 2.06% vm_setivar.isra.358
        2.02% vm_search_super_method
        0.55% vm_call_iseq_setup_normal_0start_2params_3locals
     0.97% rb_memhash
     0.97% rb_st_lookup
     0.67% vm_call_cfunc
   + 0.60% int_dotimes
+   63.10%     3.86%  ruby     ruby               [.] vm_call_cfunc
+   39.69%     5.04%  ruby     ruby               [.] gc_mark_children
+   38.83%     1.62%  ruby     ruby               [.] newobj_slowpath_wb_protected
+   35.43%     1.67%  ruby     ruby               [.] rb_str_downcase

こちらでも、私の環境では [unknown] なshared objectは出ませんでした。fpのunwindをしないのでinline化された関数の情報は見れませんが、逆に実際フレームにになっている呼び出しを見ることができます。まあこちらでも正しく割合が計測できるようになった風なので概要は正しくわかりますし、dwarfオプションに比べ計測が軽量なため結果もより正確なはずなのも利点でしょう。

一方、LBRはスタックの深さが8, 16, あるいは32フレームまでしか計測を行なってくれないという欠点があるようです。スタックが深い用途や、次に述べるFlameGraphには向かないとされています。

3. FlameGraphの出し方

perf reportの普通のcall graphの出力もシンプルでいいですが、brendangregg/FlameGraphを使うと結果をflame graphとして可視化することができます。

使い方はREADMEの通りですが、PATHを通しておくと以下のように使えます。

sudo perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg

ブラウザで開くと、小さいフレームもホバーすると何なのかわかるので便利です。以下に perf record --call-graph dwarf で計測したflame graphの例を貼っておきますので、RubyのVMがどのようなフローで処理をしているか興味のある方はどうぞ。(SVG版)

flamegraph.png

余談: ソースだけでannotateしたい場合

デバッグシンボルをつけてperfでannotateをするとasmと一緒に元になったCのソースを見ることができますが、これができるならCのソースだけ見たい、と思ったことはありませんか?
どうやらperf annotateは裏側でobjdumpを使っているだけらしく、Cのソースだけ見る、というのは私の知る限り現時点ではサポートされてないようです。

Linux perf同様にイベントをサンプリングして同じような計測ができるツールにOProfileというのがあり、LinuxでCのソースだけを見てプロファイリングをしたい場合はこちらが使えるようです。(さらに余談: macOSだとXCode InstrumentsのTime Profilerが使えそうです)

sudo apt install oprofile でインストール、 sudo operf --pid <pid> で起動して SIGINT で終了、 opannotate -s とすると計測結果とCのコードがバーッと出てきます。この記事を読んでいる人は Migrating from OProfile to perf, and beyond を逆引きすると便利かもしれません。

これ自体は便利そうなのですが、CRubyのJITコンパイラが生成するshared objectの部分ではopannotateが全く動かず、デバッグも面倒なのので私はとりあえずperf annotateで我慢することにしました。Linux perfの方が取れるイベントの種類が多いようなので、いつかperfでもどうにか同じことができるようになるといいですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

いつものように本番作業してたはずなのに

この記事は「本番環境でやらかしちゃった人 Advent Calendar 2019」の1日目です。
https://qiita.com/advent-calendar/2019/yarakashi-production

なかなか濃いラインナップが期待されますが、まずはさらっといきたいと思います。
具体性が乏しい部分もあると思いますが、そこはお察しください。。。

やらかし

背景(前提条件)

  • いっていに昔の話です
  • ETL(データ加工)サーバ
    • 数十を超えるシステムからデータを集める
    • BIツールなどで活用できるように各種加工処理を行い、DBなどにロードする
    • 繁忙の違いはあれど、24/365で常時一定量の処理は稼働している
    • 複数のチームが共存しているサーバ
      • アプリ面では比較的疎
  • ETL処理のリリース前に本番サーバ上で試験をする取り決めになっていた
    • 性能や本番相当データのテストが安全に行えるような環境が(当時は)存在しなかった
    • 修正リリースの場合、当該処理が動かない時間帯を狙って試験を行う(当然)
  • 私はアプリチーム

問題編(経緯)

  • ある日、チームメンバ(Aさんとする)がいつも通りの修正リリースすることを承認し、作業自体は任せていた
    • よくある修正で規模も小さく、局所的な対応のため、いつも通りやっといてください、という形で
  • しばらくすると、隣のチームの電話がなった。定常ジョブが10以上複数エラー終了したと連絡あり。
  • そのとき自分は時間も権限もあったので、軽い気持ちで「ジョブ見ますよー」と言って、作業部屋に移動。
  • SSHログインしたものの、ほとんどのコマンドが通らない。
    • cdは通る。lsやそのたツールのコマンドが通らない
    • この時点でいやーな予感はしたが。。。
  • すると他のチームメンバの電話もバンバン鳴り出した。ジョブが落ちまくっているらしい。だが調査もできないので焦りが増していく。。

さて何が起きたでしょうか、、わかる人はわかるのでは。。。

その時の思考と行動

  • あれ、コマンド通らないのか、なんでだろ。しかも一部?
  • 急にドカンドカン落ちるのか、ハード系障害かなあ、流石に影響範囲広いし
  • そういや何やってんだろ、Aさん〜
    • Aさん「試験できなくなっちゃって、いったん障害対応優先ですかねー」
    • 自分「そうっすねー、どこまでやったんですか?」
    • Aさん「ちょうど試験用に共通ユーザの環境変数を書き換えたところです、試験用のモジュールを置く場所決めて、別途読み込めるようにしたんですけどね」
    • 自分「なるほどー。。。えっ何それ」
    • Aさん「.profileのPATHを直接書き換えましたよー」
    • 自分「…それやん絶対。。。」

原因

  • バッチ処理が使っている共通ユーザの.profile手動でエディタで 書き換えた
  • その際、PATHのあるある間違いをやってしまった
#(修正前)
export PATH=$PATH:/app/bin
#(修正後)
export PATH=/home/xxx/work_test/bin
  • 結果バッチ処理含め大量にエラーが発生

対応

  • 部屋全員に「動くな!」と叫ぶ(logout禁止)
  • lsなどが通る、修正前のprofileでログインしている人を探した
  • その人のターミナルを大事にして、.profileを元に戻した
  • 周知し、ジョブの再実行大会を促す
  • やってたリリース作業は延期。

ということで、以下は本アドベントカレンダーの必須項目です

振り返り

惨劇はなぜおこってしまったのか

  • 普段の手順と変わっていたことに気づかなかった
    • 今までは本番のモジュールを上書きして手動テストしていた
    • Aさんは上書きよりも別場所においてテストしてから、確認済みのものを上書きすれば良いのでは?と考えた
    • 考えて工夫した結果ではあったが、裏目にでた
  • 本番に手をいれる作業についての影響を甘くみていた
    • その作業が他の何に影響を及ぼすのか、ということは常に考えないと、本番環境だから。。。
      • 個別モジュール上書きだけなら自分のチームしか最悪落ちないが、、
    • 特にエディタで直接編集する、のようなアドホックな(ヒューマンエラーが混入しやすい)手順になっていた

二度と惨劇を起こさないためにどうしたのか

  • ヤバイファイルはカジュアルにさわれないように権限制御
    • アプリチームが触れないroot管理に
  • 経緯をまとめてグループ内へ周知、教育
    • 個人的に、新人などには影響ないところでPATHエラーを踏ませたりして、身をもって学ぶようにさせた
  • その他(人の力で回避。チェック強化とか。。。)

終わりに

  • 設計時にどの程度機能分離するか、やリリース時の手順をどうするか、などを考えるときに毎回思い出します
  • 結局のところヒューマンエラーなので、仕組み化、自動化などで人の手をできる限りかけないようにするのが本質的には良いとは思います
    • 今の時代なら、安価・容易に、クラウド、各種サービスなどの組み合わせ、すなわち技術で解決できる、解決すべきである、と思います

以上です。。2日目以降も楽しみにしています!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux開発環境の構築メモ

はじめに

Web系の開発環境として長年Windowsを使っていましたが、数ヶ月前にLinux環境に切り替えました。

使用環境が安定してきたので、利用環境構築の備忘録として使用中のソフトとインストール方法を簡単にまとめました。

利用環境紹介

OS

Ubuntu 18.04

ディストリビューションは特にこだわり無いため、シェアの高いものを選びました。
デスクトップ環境ですが、低スペックPCの再利用などの用途では無いため、デフォルトのGNOMEを使っています。

最小設定でインストールしました。

パーティションも、デフォルト設定です。
500GBのSSDなので、
ブートローダー用の「EFIシステムパーティション(/boot/efi)」が500MBほど、
残りがルート(/)領域で設定されました。

外観/Ubuntuの設定

標準の設定ツールではテーマやフォントの変更ができないため、tweakをインストールします。

Ubuntu標準のソフトウェア管理ツール「Ubuntu software」でインストールするか、下記コマンドでインストール

sudo apt install gnome-tweaks

テーマ

下記のように設定しました

  • アプリケーション:materia-dark
  • カーソル:paper
  • アイコン:paper
テーマインストール
sudo add-apt-repository ppa:dyatlov-igor/materia-theme
sudo apt update
sudo apt install -y materia-gtk-theme
アイコンインストール
sudo add-apt-repository -u ppa:snwh/ppa
sudo apt install -y paper-icon-theme

フォント

Ricty Diminishedをインストールしました。

インストール
sudo apt install -y fonts-ricty-diminished

設定はとりあえず下記の感じに
Screenshot from 2019-11-30 20-42-27.png

アプリ切り替えをウィンドウ単位に変更

デフォルトでは「Alt+Tabキー」での切り替えがアプリ単位となる。
Windowsと同じように、ウィンドウ単位での切り替えとなるよう、設定画面からキーバインドを変更する

設定ツールを開き、「Device」→「Keyboard」の中の「Switch Windows」に「Alt+Tabキー」を設定する

日本語環境のインストール

こちらを参考にインストールしました。

普通にaptからインストールすると、日本語切替時のデフォルトが英語モードとなったり、辞書の性能が低かったりします。

日本語の変換はSuper(Win)+Spaceとなっています。

ターミナル/シェル

terminator

ターミナルエミュレータにterminatorを設定しました。

インストール
sudo apt install -y terminator

ほぼこちら方の設定をそのまま使っています。参考リンク

また、下記を追加で設定しました。

  • hide_windowのショートカットキーを「Ctrl+T」に変更
  • 設定の「一般」タブの「フォーカスから外れたら隠す」にチェックを入れる

コマンドが必要なときだけ「Ctrl+Tabキー」を押してターミナルで操作し、「Alt+Tabキー」などでエディタに戻ると自動でターミナルが閉じてくれます。

fish

シェルはfishを使っています。
コマンドやディレクトリ名の補完機能が便利です。

bashと書式が違うため、bashのスクリプトでは動かないものがあったりしますが、ほぼ初期状態で十分使えるのがおすすめです。
テーマはシンプルな「clearance」に設定しました。

また、aliasなどをbashで設定し、.bashrcの末尾に"exec fish"を記載してbash経由で起動しています。

.bashrc
...
exec fish
  • fishのインストール
    インストールは公式の情報を参考にしました。
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt-get update
sudo apt-get install fish
  • fishermanのインストール
    プラグイン管理のツールもインストールします。(参考
curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
  • テーマの変更
    テーマはシンプルな「clearance」をインストールしました。
fisher add oh-my-fish/theme-clearance
  • プラグイン:bassのインストール

fishでbashコマンドを使えるようにするためのプラグインです。

インストール
fisher add edc/bass

bashのスクリプトも下記のように動かすことができます。

bass test.sh
bass source config.sh
  • プラグイン:pecoのインストール

pecoは入力された一覧から絞り込み検索と、選択ができるようになるツールだそうです。(参考)

いろいろな用途があるようですが、今回はhistoryの検索を設定しています。

インストール
sudo apt install peco
fisher add oh-my-fish/plugin-peco

下記設定ファイルに追加

~/.config/fish/config.fish
function fish_user_key_bindings
  bind \cr 'peco_select_history (commandline -b)'
end

設定の反映

 source ~/.config/fish/config.fish

キーバインドの設定

Xkeysnail

カーソルキーの移動などを設定したかったので、キーリマップツールを設定しました。

インストール方法

公式ページを参照してください。

① インストール

sudo apt install python3-pip
sudo pip3 install xkeysnail

② 設定ファイルを~/.Xkeysnail/config.pyに保存する

③ 起動

sudo xkeysnail ~/.Xkeysnail/config.py

エラーが起きる場合は下記を実行した後に、上記コマンドを実行してください

xhost +SI:localuser:root

PC起動時に実行する方法

コマンドを毎回打つのは面倒なので、自動起動の設定を行います。
デーモン化させる方法がいくつか紹介されていましたが、自分の環境では頻繁に停止して、その度に再実行が必要でした。

そのため、.bashrcに起動コマンドを書いて起動させる方法で設定します。

① xkeysnailをパスワード無しでsudo実行させる

visudo で下記を追記します。
※ちなみに、私の環境では/usr/local/bin/xkeysnailにインストールされていました。

// 設定を開く
sudo visudo

// 下記行を追加
user_id ALL=NOPASSWD: /usr/local/bin/xkeysnail

.bashrcに自動起動の設定を記載

.bashrc
if [ -z `pgrep xkeysnail` ]; then
  xhost +SI:localuser:root
  sudo xkeysnail /home/user_id/.Xkeysnail/config.py -q > /dev/null &
fi

※起動中の確認にpgrepを利用しましたが、他に良い方法があるかも知れません。

エディタ

vim

ちょっとした設定変更に利用。
カーソル移動でABCDのような記号が入力されるようになったため、設定します。
~/.vimrcに下記を追加して保存

.vimrc
set nocompatible

nano

同じくターミナル上での編集用に利用

開発ツール

下記のものをインストールして使っています。

git

言わずと知れたバージョン管理ツール

クライアントはコマンドラインとPhpStormを使っています。

ssh

最小構成では入っていないため、後から入れる必要があります。

$ sudo apt install openssh-server

とりあえずrootログインとパスワードログインを無効化

/etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no

Docker/docker-compose

開発環境はほぼDocker内に設定しています。

公式サイトに従ってインストール

Docker
Docker Compose

ちなみに、docker-composeを毎回打つのは面倒なので、下記エイリアスを設定しています。
(2番めは本番環境用ファイルの起動用)

.bashrc
alias doc='docker-compose'
alias docp='docker-compose -f prod.docker-compose.yml'

PhpStorm

IDEはJetBrain派です。

特に設定しなくても便利に使えます。
DB閲覧やGit管理など、ほぼこれ1台でまかなっています。

Toolbox Appをインストールして管理しています。

設定は、ファイルにエクスポートしてクラウドに保存しています。
(設定はアカウントに紐付けて自動同期でやれれば良いのですが、他PCにインストールしたときに、すべてのPCの設定が初期状態に上書きされたり、管理が良くわかりませんでした。)

VSCode

Microsoft製のIDE
主にメモ書きくらいしか使っていない・・・

リモートデベロップとか便利な機能を使ってみたいが

余談ですがIntelij系をメインにする問題は、後輩とかにVSCodeのショートカットキーを聞かれたときに即答できない。

Node.js

ホストにはあまりものを入れたくないのですが、IDEからLintツールで整形するときなど、コンテナ内だとうまく設定できなかったためホスト側に入れています。

nvmからインストールしました。

インストール
// nvmのインストール
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.0/install.sh | bash

// Node.jsのインストール
nvm install --lts

// ついでにyarnもインストール
npm install -g yarn

終わりに

IDEの設定は省いていますが、一通り開発できる環境が整いました。
今後、もっと良いツールがあれば追記していく予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux コマンド rsync リモートマシンとのやり取り

目的

  • 業務内でコマンドrsyncを使用したので忘れないようにまとめる

コマンドの例

  • 下記にrsyncを用いてローカルマシンからリモートマシンにファイルをrsyncするコマンドを記載する。

    # カレントディレクトのフォルダAの中身をリモートのフォルダBにrsyncしたいとき
    $ rsync -av -e ssh ./フォルダA/ リモートユーザ名@IPアドレス フォルダパス/フォルダB
    
    # カレントディレクトリのフォルダAをリモートのフォルダB直下にrsyncしたいとき
    $ rsync -av e ssh ./フォルダA リモート先ユーザ名@IPアドレス フォルダパス/フォルダ名B
    

より具体的な例(ローカルの指定フォルダの中身を同期)

  • リモートマシンはIP: XXX.XXX.XXX.XXX ユーザ名: miriwo_remoteとする。
  • 下記にローカルマシンのフォルダ~/testの中身をリモートマシンのフォルダパス~/直下のフォルダtest_rsyncにrsyncするときのコマンドを記載する。

    $ rsync -av -e ssh ~/test/ miriwo_remote@XXX.XXX.XXX.XXX ~/test_rsync
    

より具体的な例(ローカルの指定フォルダを同期)

  • リモートマシンはIP: XXX.XXX.XXX.XXX ユーザ名: miriwo_remoteとする。
  • 下記にローカルマシンのフォルダ~/testをリモートマシンのフォルダパス~/直下のフォルダtest_masterにrsyncするときのコマンドを記載する。

    $ rsync -av -e ssh ~/test miriwo_remote@XXX.XXX.XXX.XXX ~/test_master
    
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む