- 投稿日:2019-12-03T19:38:39+09:00
SSH ポートフォワーディング時に Bad local forwarding specification エラーでハマった話
SSH ポートフォワーディングについては下記記事がわかりやすいです。
SSH ポートフォワーディング とは再現した環境
- macOS Mojave / Catalina
- OpenSSH_7.9p1, LibreSSL 2.7.3
エラーでハマる
いつものように下記コマンドを叩いた。
ssh -L ローカルのポート番号:接続したいサーバ:接続したいサーバのポート番号しかし、エラーが出て、動作しなかった!
Bad local forwarding specification 'ローカルのポート番号:接続したいサーバ:接続したいサーバのポート番号'スペースが足りなかったり、余分なスペースが入ると出るエラーらしい(参考)が、
確認しても間違いが見つからなかった。原因
Mac のデフォルトのメモ帳からコマンドをコピペして、そのままコマンドラインに貼り付けていたから。
形式が勝手に変わってしまうから?
本当の原因は不明...尚、メモ帳のコマンドをコピーして、 Slack などに一度ペーストし、更に Slack にペーストしたコマンドをコピーしてコマンドラインにペーストすると、動作する。(なぜ...)
何度も使うコマンドを Mac のデフォルトのメモ帳に保存しておくことがあるが、動作しないこともあるので注意するべきなのかもしれない。
- 投稿日:2019-12-03T19:07:08+09:00
ShellScript Bash 変数に「*」を格納して出力する時に少し詰まったところ
目的
- ShellScriptのBashで変数に文字列として
*を出力する際に詰まったところをまとめる結論
- 変数を出力するときに変数名を
""で囲むecho "${変数名}"筆者が困った流れ
- 変数
FOOに*を格納して出力したくなった。下記コマンドを実行して
*を変数FOOに格納した。FOO="*"
~/ディレクトリで下記コマンドを実行して変数FOOを展開しようとしたが、カレントディレクトリのフォルダが出力されてしまった。echo ${FOO} >Applications Desktop Documents Downloads Library Movies Music Pictures Public tig workspace
*が出力されない・・・。解決方法
- 変数名を
""で囲むことで出力することができた。下記に
*を出力する方法を記載する。$ echo "${FOO}" >*
- 投稿日:2019-12-03T17:31:13+09:00
#Linux の touch でファイル作成をする時にディレクトリが存在しなくてもエラーを起こさない mkdir -p みたいなエイリアスを作る
settiing
以下をコンソールで直接実行
あるいは
~/.zshrc ~/.bashrc などにエイリアスを登録して関数を作る
function touchp() { mkdir -p $(dirname "$1"); touch "$1"; }execute
touchp ~/too/deep/dir/dir/dir/file.txtRef
mkdir + touch を実現するコマンドinstall - Qiita
Original by Github issue
- 投稿日:2019-12-03T16:20:38+09:00
Linux コマンドを打った自分のログを取得していく方法
- 投稿日:2019-12-03T16:11:42+09:00
ZynqMP で Linux の CMA 領域を devicetree の reserved-memory で指定した時のアライメントは 0x00400000(4MiB) 単位
Linux ではデバイスツリーで次のように reserved-memory(予約メモリ)空間を指定出来ます。
devicetree.dts/ { #address-cells = <2>; #size-cells = <2>; image_buf0: image_buf@0 { compatible = "shared-dma-pool"; reusable; reg = <0x0 0x6fc00000 0x0 0x00400000>; alignment = <0x0 0x1000>; label = "image_buf0"; }; };この時、resuable プロパティを付けることによって、予約したメモリ領域を CMA 領域として使うことが出来ます。例えば ZynqMP-FPGA-Linux で上記のデバイスツリーを追加して Linux Kernel を起動すると、次のようなログが出ます。
Starting kernel ... [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034] [ 0.000000] Linux version 4.19.0-xlnx-v2019.1-zynqmp-fpga (ichiro@Jabberwock) (gcc version 7.4.0 (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04)) #2 SMP Wed Jul 17 15:19:07 DST 2019 [ 0.000000] Machine model: Avnet Ultra96 Rev1 [ 0.000000] efi: Getting EFI parameters from FDT: [ 0.000000] efi: UEFI not found. [ 0.000000] Reserved memory: created CMA memory pool at 0x000000006fc00000, size 4 MiB [ 0.000000] OF: reserved mem: initialized node image_buf@0, compatible id shared-dma-pool [ 0.000000] cma: Reserved 256 MiB at 0x0000000070000000 : : :このログを見てわかるように、0x000000006fc00000 から 4MiB が CMA 領域として確保されています。
実はこの件に関して udmabuf に issue があげられました。
- 「Can't set physical address in device tree for Zynq MPSoC」 https://github.com/ikwzm/udmabuf/issues/29
この issue によれば、次のようなデバイスツリーの設定だと、
devicetree.dtsreserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; rproc_0_reserved: rproc@3ed00000 { no-map; reg = <0x0 0x3ed00000 0x0 0x1000000>; }; image_buf0: image_buf@0 { compatible = "shared-dma-pool"; reusable; reg = <0x0 0x6fc00000 0x0 0x0100000>; alignment = <0x0 0x1000>; label = "image_buf0"; }; }; udmabuf@0 { compatible = "ikwzm,udmabuf-0.10.a"; device-name = "udmabuf0"; size = <0x0 0x0100000>; memory-region = <&image_buf0>; };"incorrect alignment of CMA region" というエラーが出て CMA 領域の確保に失敗します。
[ 0.000000] Reserved memory: incorrect alignment of CMA region [ 0.000000] cma: Reserved 256 MiB at 0x000000005fc00000 : : : [ 127.914295] udmabuf udmabuf@0: of_reserved_mem_device_init failed. return=-22 [ 127.921580] udmabuf udmabuf@0: driver installed. [ 127.926204] udmabuf: probe of udmabuf@0 failed with error -22 [ 127.932553] udmabuf udmabuf.0: DMA mask not set [ 127.937692] udmabuf udmabuf0: driver version = 1.4.5 [ 127.942653] udmabuf udmabuf0: major number = 240 [ 127.947439] udmabuf udmabuf0: minor number = 0 [ 127.952052] udmabuf udmabuf0: phys address = 0x000000005fd00000 [ 127.958140] udmabuf udmabuf0: buffer size = 1048576 [ 127.963274] udmabuf udmabuf0: dma device = udmabuf.0 [ 127.968582] udmabuf udmabuf0: dma coherent = 0 [ 127.973195] udmabuf udmabuf.0: driver installed.そこで Linux Kernel のソースコードを見てみると、kernel/dma/contiguous.c に次のような記述がありました。
kernel/dma/contiguous.cstatic int __init rmem_cma_setup(struct reserved_mem *rmem) { phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); phys_addr_t mask = align - 1; unsigned long node = rmem->fdt_node; struct cma *cma; int err; if (!of_get_flat_dt_prop(node, "reusable", NULL) || of_get_flat_dt_prop(node, "no-map", NULL)) return -EINVAL; if ((rmem->base & mask) || (rmem->size & mask)) { pr_err("Reserved memory: incorrect alignment of CMA region\n"); return -EINVAL; } err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma); if (err) { pr_err("Reserved memory: unable to setup CMA region\n"); return err; } /* Architecture specific contiguous memory fixup. */ dma_contiguous_early_fixup(rmem->base, rmem->size); if (of_get_flat_dt_prop(node, "linux,cma-default", NULL)) dma_contiguous_set_default(cma); rmem->ops = &rmem_cma_ops; rmem->priv = cma; pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n", &rmem->base, (unsigned long)rmem->size / SZ_1M); return 0; } RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);align 変数でアライメント単位を設定してから、開始アドレス(
rmem->base) と容量(rmem->size) がアライメント単位であるかどうかチェックしています。アライメント単位は MAX_ORDER 定数や pageblock_order 変数(or定数) によって算出されますが、ZynqMP-FPGA-Linux では 0x00400000 になります。したがって、ZynqMP で Linux の CMA 領域を devicetree の reserved-memory で指定した時のアライメントは 0x00400000(4MiB) 単位であることがわかります。
- 投稿日:2019-12-03T13:29:58+09:00
Linux iostatで負荷状況見る
必要な物
# yum install sysstat 読み込んだプラグイン:fastestmirror Loading mirror speeds from cached hostfile * base: ftp.riken.jp * elrepo: ftp.yz.yamagata-u.ac.jp * epel: ftp.riken.jp * extras: ftp.riken.jp * updates: ftp.riken.jp 依存性の解決をしています --> トランザクションの確認を実行しています。 ---> パッケージ sysstat.x86_64 0:10.1.5-18.el7 を インストール --> 依存性解決を終了しました。 依存性を解決しました ==================================================================================================================================================================== Package アーキテクチャー バージョン リポジトリー 容量 ==================================================================================================================================================================== インストール中: sysstat x86_64 10.1.5-18.el7 base 315 k トランザクションの要約 ==================================================================================================================================================================== インストール 1 パッケージ 総ダウンロード容量: 315 k インストール容量: 1.1 M Is this ok [y/d/N]: y Downloading packages: sysstat-10.1.5-18.el7.x86_64.rpm | 315 kB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction インストール中 : sysstat-10.1.5-18.el7.x86_64 1/1 検証中 : sysstat-10.1.5-18.el7.x86_64 1/1 インストール: sysstat.x86_64 0:10.1.5-18.el7 完了しました! # iostatオプション無しで実行
# iostat Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 1.94 0.00 2.06 9.83 0.00 86.17 Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn sda 12.09 4.41 527.38 20345221 2433107135 sdb 7.93 7.28 176.23 33578666 813072749 dm-0 20.04 11.67 703.58 53828027 3246005722 dm-1 0.01 0.01 0.04 65456 171988 #CPUの使用率を1秒間隔で5回表示
# iostat -c 1 5 Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 1.94 0.00 2.06 9.83 0.00 86.17 avg-cpu: %user %nice %system %iowait %steal %idle 38.57 0.00 5.71 55.71 0.00 0.00 avg-cpu: %user %nice %system %iowait %steal %idle 19.80 0.00 2.97 75.25 0.00 1.98 avg-cpu: %user %nice %system %iowait %steal %idle 20.00 0.00 3.00 77.00 0.00 0.00 avg-cpu: %user %nice %system %iowait %steal %idle 12.90 0.00 4.30 81.72 0.00 1.08 #-t(時刻表示)した場合
# iostat -c -t 1 5 Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) 2019年12月03日 13時22分45秒 avg-cpu: %user %nice %system %iowait %steal %idle 1.94 0.00 2.06 9.83 0.00 86.17 2019年12月03日 13時22分46秒 avg-cpu: %user %nice %system %iowait %steal %idle 8.33 0.00 8.33 78.33 0.00 5.00 2019年12月03日 13時22分47秒 avg-cpu: %user %nice %system %iowait %steal %idle 36.23 0.00 5.80 57.97 0.00 0.00 2019年12月03日 13時22分48秒 avg-cpu: %user %nice %system %iowait %steal %idle 11.76 0.00 5.88 78.82 0.00 3.53 2019年12月03日 13時22分49秒 avg-cpu: %user %nice %system %iowait %steal %idle 41.46 0.00 7.32 51.22 0.00 0.00 #ディスクの使用率を1秒間隔で5回表示(-mはMB単位で出すオプション)
# iostat -d -m 1 5 Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 12.10 0.00 0.52 19869 2377370 sdb 7.93 0.01 0.17 33609 795006 dm-0 20.04 0.01 0.69 53385 3172207 dm-1 0.01 0.00 0.00 63 167 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 32.14 0.00 4.53 0 3 sdb 47.62 4.56 2.37 3 1 dm-0 79.76 4.56 7.15 3 6 dm-1 0.00 0.00 0.00 0 0 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 44.44 0.00 9.18 0 6 sdb 52.78 0.00 3.99 0 2 dm-0 97.22 0.00 13.42 0 9 dm-1 0.00 0.00 0.00 0 0 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 7.89 0.00 2.19 0 0 sdb 47.37 0.00 10.07 0 3 dm-0 73.68 0.00 20.25 0 7 dm-1 0.00 0.00 0.00 0 0 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 24.32 0.00 3.77 0 2 sdb 48.65 5.17 8.83 3 6 dm-0 67.57 5.17 7.77 3 5 dm-1 0.00 0.00 0.00 0 0 #-t(時刻表示)した場合
# iostat -d -m -t 1 5 Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) 2019年12月03日 13時21分59秒 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 12.10 0.00 0.52 19868 2376780 sdb 7.93 0.01 0.17 33234 794557 dm-0 20.04 0.01 0.69 53009 3171168 dm-1 0.01 0.00 0.00 63 167 2019年12月03日 13時22分00秒 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 27.63 0.00 7.19 0 5 sdb 31.58 5.04 4.07 3 3 dm-0 78.95 5.04 13.19 3 10 dm-1 0.00 0.00 0.00 0 0 2019年12月03日 13時22分01秒 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 29.07 0.00 5.19 0 4 sdb 40.70 0.00 2.34 0 2 dm-0 59.30 0.00 6.55 0 5 dm-1 0.00 0.00 0.00 0 0 2019年12月03日 13時22分02秒 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 19.32 0.00 5.70 0 5 sdb 19.32 4.35 1.19 3 1 dm-0 43.18 4.35 7.97 3 7 dm-1 0.00 0.00 0.00 0 0 2019年12月03日 13時22分03秒 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 27.03 0.00 4.37 0 3 sdb 70.27 5.17 6.04 3 4 dm-0 85.14 5.17 7.71 3 5 dm-1 0.00 0.00 0.00 0 0 #-p(ディスクを限定)した場合
# iostat -d -m -p sda 1 5 Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 12.10 0.00 0.52 19869 2378034 sda1 0.00 0.00 0.00 27 2 sda2 12.10 0.00 0.52 19840 2378032 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 46.67 0.00 8.13 0 4 sda1 0.00 0.00 0.00 0 0 sda2 46.67 0.00 8.13 0 4 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 21.28 0.00 5.36 0 5 sda1 0.00 0.00 0.00 0 0 sda2 21.28 0.00 5.36 0 5 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 26.14 0.00 5.25 0 4 sda1 0.00 0.00 0.00 0 0 sda2 26.14 0.00 5.25 0 4 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 39.13 0.00 9.90 0 2 sda1 0.00 0.00 0.00 0 0 sda2 39.13 0.00 9.90 0 2 #-N(LVMのデバイス名)した場合
# iostat -d -m -N 1 5 Linux 3.10.0-514.el7.x86_64 (hostname) 2019年12月03日 _x86_64_ (1 CPU) Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 12.10 0.00 0.52 19869 2378157 sdb 7.94 0.01 0.17 34092 795626 cl-root 20.04 0.01 0.69 53868 3173614 cl-swap 0.01 0.00 0.00 63 167 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 17.17 0.00 3.31 0 3 sdb 25.25 7.73 1.77 7 1 cl-root 43.43 7.73 5.08 7 5 cl-swap 0.00 0.00 0.00 0 0 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 28.75 0.00 7.78 0 6 sdb 23.75 0.00 3.48 0 2 cl-root 55.00 0.00 10.69 0 8 cl-swap 0.00 0.00 0.00 0 0 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 26.67 0.00 4.49 0 3 sdb 72.00 5.10 2.90 3 2 cl-root 108.00 5.10 7.88 3 5 cl-swap 0.00 0.00 0.00 0 0 Device: tps MB_read/s MB_wrtn/s MB_read MB_wrtn sda 37.84 0.00 8.53 0 6 sdb 29.73 0.00 3.51 0 2 cl-root 94.59 0.00 20.02 0 14 cl-swap 0.00 0.00 0.00 0 0 #
- 投稿日:2019-12-03T10:47:24+09:00
プロセス間通信の種類
Introduction of Communication
agenda
WHOAMI
IPFactory 1年 @n01e0
普段はLinuxのカーネルモジュールを作ったりしています。WHAT IS IPC
IPCとは Inter Process Communication の略称である。
プロセス間でのデータのやり取りを意味し、Linuxにおいては、様々な種類のIPCが用意されている。
本記事ではそれぞれの軽い紹介程度に留め、実装について詳細な説明は行わない。
各機能のおおまかな特徴を理解し、読者にとっての最適な選択が出来ることを目標としている為である。IPCの分類
IPCはその機能により大きく3つに分類される
- 通信
- プロセス間のデータ通信、交換に関する機構
- 同期
- プロセス、スレッド間の同期に関する機構
- シグナル
- シグナルは特殊で、条件によっては同期にも通信にも用いることが出来る
IPCの仕様
IPCはUNIXの長い歴史の中でいくつかの規格に沿って実装されており、混在している。
主にSystem Vの実装とPOSIXの実装がある
全体的にPOSIXの方が扱いやすくなってはいるが、POSIXのIPCはカーネルバージョン2.6から実装されている為、可搬性には劣る。SYSTEM V IPC と POSIX IPC
System Vにおいて、各IPCのデータ構造は、カーネル空間にあり、
プロセスがIPC資源(セマフォ、メッセージキュー、共有メモリリージョン)を要求した時に動的に生成される。
各IPC資源は固有の識別子を持ち。ユーザーは各IPCをそれとは異なるIPCキーで区別出来る。
この関係はファイルとファイルディスクリプタの関係に似ている。
しかし、ファイル異なる点として、プロセスが明示的に解放しない限り、メモリ上に存在し続ける。
同様の機能を提供するPOSIX IPCがあり、こちらはマルチスレッドセーフな設計になっている。
もう1つの大きな差異としては、POSIXでは各IPCに名前を付けて区別できる点がある。
命名には規則があり、/で始まり、/以外の1文字以上の長さのnull終端の文字列でなければいけない。
仕様に細かな違いはあるが、各IPCの概念で大きく異なるのは各オブジェクト(資源)の管理方法であるIPCの比較
System VとPOSIXの大きな違いとしてIPCオブジェクトの識別子、ハンドラがあり、これらを列挙する。
IPC種別 識別子 ハンドラ パイプ なし ファイルディスクリプタ FIFO パス ファイルディスクリプタ System Vセマフォ System V IPCキー System V IPC ID POSIX 無名セマフォ なし セマフォポインタ POSIX 名前付きセマフォ POSIX IPCパス セマフォポインタ System Vメッセージ System V IPCキー System V IPC ID POSIXメッセージ POSIX IPCパス メッセージキューディスクリプタ System V共有メモリ System V IPCキー System V IPC ID POSIX共有メモリ POSIX IPCパス ファイルディスクリプタ UNIXドメインソケット パス ファイルディスクリプタ インターネットドメインソケット IPアドレス ポート ファイルディスクリプタ 本記事で紹介するLinuxにおけるIPC
PIPE
パイプとは
日常、シェルで生活をしている読者にとっては非常に慣れ親しんだ概念だろう。
シェルにおけるパイプ(|)とは何なのか、改めて簡単に記すと
あるプロセスの出力を別のプロセスの入力につなげる
といった意味になる。
IPCとしてのパイプも同様、データの出力と入力を繋げる為に用いられる事が多い。
パイプのデータ構造について、何かを例に説明しようと思ったが、パイプ以外に良い例が浮かばない。
筒なので、入出力は先入れ先出しとなる。
まとめると、パイプとは単方向の先入れ先出し型データ構造である。実装
unistd.hで定義されているpipe()システムコールは2つのファイルディスクリプタを生成する。
一方は読み出し用、もう一方は書き込み用となる。
これらは、ファイルディスクリプタではあるが、対応するパスは無い。
パイプに書き込まれたデータは、読み出されるまでカーネル内のデータ構造によってバッファリングされる。
通常、空のパイプに対してプロセスが読み込み(read())を行うと、そのパイプにデータが書き込まれるまで、読み込みは停止する。FIFO
類似した機能として
FIFOが存在する。
名前付きパイプとも呼ばれ、また名前の通り先入れ先出しのデータ構造である
パイプと異なる点は、作られるファイルディスクリプタに名前(パス)があるという点くらい。SIGNAL
これもまた、慣れ親しんだ概念だろう。
シグナルもIPCの一種であると言える。
シグナルには多くの種類があるので、一部を例にとって挙げると
SIGHUPSIGINTSIGQUITSIGKILLSIGSEGVなどがある。
シグナルは主に、プロセスに対し何かが発生したことを伝える時、プロセスに特定の動作をさせる時に用いられている。
シグナルの持つ情報量は少なく、通常は番号(種類)以外の情報は持たない。
また、受け取ったシグナルをどう扱うかはプロセス次第である。対応
シグナルへの対応にはいくつかパターンがある
1. 無視
1. 標準設定の動作を実行する
1. シグナルハンドラを呼び出す無視
一部を除き、受け取ったシグナルを無視する事もできる。
無視できない一部のシグナルとは
SIGKILLSIGSTOPであり、これらのシグナルを受け取ったプロセスは、必ず標準設定動作を実行する。
標準設定動作
その標準設定動作とは、名前の通りLinuxにおいて標準で設定されている各シグナルに対する反応である。
プロセスの終了やダンプ、停止、標準で無視が設定されているシグナルもある。シグナルハンドラ
標準設定動作以外にも、
signal()を用いてユーザーが各シグナル毎の対応を定義できる。実装
プロセスがプロセスに対し、シグナルを発行すると、シグナルはカーネルによって受け取られる。
カーネルは対象のプロセスが実行中かどうかを調べ、実行中でなかった場合にはシグナルを保留状態にする。
signal()システムコールは引数にシグナルの種類と対応するシグナルハンドラとなる関数のポインタを持ち、それらを対応づける。SEMAPHORE
セマフォはIPCの分類の中でも、同期機構にあたる。
セマフォの実態は整数値である。
複数プロセスで共有する資源の保護の為、アクセス制御のカウンタとして割り当てられで構成される。
構成
整数型の変数
カウンタとなる。この値が資源の状態(使用可能か否か)を示す
操作待ち状態にあるプロセスのリスト
資源が使用可能になるまで待機しているプロセスのリスト
2つのアトミックなメソッド
セマフォのカウントアップ、ダウンを行う。
セマフォが保護している資源にプロセスがアクセスする時、まず対象資源に紐付けられたセマフォをカウントダウンする。
もしそのセマフォのカウントが負になった場合、プロセスの実行は中断され、リストに加えられる。
資源へのアクセスが終わると、プロセスはセマフォをカウントアップする。
これによりセマフォの値が正になると、リストのプロセスが再開される。実装
セマフォ自身がプロセスの動作を制限する訳ではなく、セマフォに意味を持たせるのはあくまでユーザーである。
また、セマフォは同期機構である為、非常に複雑な操作を必要とする。System V
semget()によりセマフォを作成、または開く。
semop()によってセマフォの操作を行う。POSIX
POSIXでは、セマフォは2種類存在する
- 名前付きセマフォ
- メモリベースドセマフォ(無名セマフォ)名前付きセマフォ
POSIXの他のIPC同様、セマフォに名前を付けて管理出来る。
名前を共有する事で、プロセス間でセマフォを共有するメモリベースドセマフォ
共有メモリにマッピングされる。
名前を持たず、プロセス、スレッド間でメモリの共有によってセマフォを共有する。MESSAGE
IPCメッセージキューは名前の通りキューである。
プロセスによって送信されたメッセージは、他のプロセスが読み込むまでメッセージキューに置かれる。
他のプロセスがメッセージを読み込むと、カーネルはメッセージをキューから削除する。
そのため、プロセス間でのメッセージのやり取りは必ず一対一となる。実装
System V
メッセージとして送信されるデータは、必ずメッセージの優先度を整数値で指定する必要がある。
受信側は、優先度を指定してメッセージを受け取る。
(となると、先入れ先出しではなくなることもあるのでキューと呼んで良いものなのか)
msgget()を用いてキューを取得し、messnd()で送信、msgrcv()で受信する。POSIX
POSIXメッセージキューも名前を付けて管理する。
受信の際、メッセージの優先度を指定する事は出来ない。
最も高い優先度の、最も古いメッセージが読み出される。
mq_open()でキューを開き、mq_sendで送信、mq_receiveで受信を行う。SHARED MEMORY
IPC共有メモリ
名前の通り、共有するメモリ空間に特定のデータ構造を配置する。
また、他のIPCは実行時にユーザー空間からカーネル空間のデータ構造へデータを転送していたのに対し、共有しているメモリ空間へマッピングするだけなのでオーバーヘッドも小さい。
しかし、カーネルが介していないという点には留意すべき問題もある。
複数プロセスが同時にアクセスするのを防ぐ必要性があり、その為には先述のセマフォを用いる事が出来る。実装
System V
shmget()により、共有メモリセグメントを作成、または既存セグメントのIDを取得shmat()により、自プロセスのメモリ空間に共有メモリセグメントをアタッチshmdt()により、デタッチする。アタッチされた共有メモリセグメントはプログラム内の通常のメモリと何ら違いなく扱える。
共有メモリオブジェクトが破棄されるのは、すべてのプロセスがデタッチしshmctl()により削除された時である。POSIX
shm_open()によって共有メモリオブジェクトをオープンする。また、この戻り値はファイルディスクリプタである。- 得られたファイルディスクリプタに対し、
MAP_SHAREDフラグをセットしてmmap()するSOCKET
ソケット。
ソケットはデータの転送方式によって2つに分類でき、
- ストリームソケット
- データグラムソケット
と呼ばれる。
ストリームソケットは名前の通りストリームとして扱え、ファイル等と同様、書き込んだサイズに関わらず任意のバイト数読み取れる。
データグラムソケットはメッセージ等と似ており、データに特定の区切りがあり、読み取りではデータ全体を読み取る必要がある。
また、ソケットのもう一つの分類として、通信先での分類もある
- UNIXドメインソケット
- インターネットドメインソケット
と呼ばれ、
UNIXドメインソケットは同一ホスト内でのアプリケーション間の通信を、インターネットドメインソケットではインターネットプロトコルで接続されたアプリケーション間の通信をサポートしている。実装
ソケットの操作に関するシステムコールは
socket()
- 新規ソケットを作成する
bind()
- ソケットをアドレスに結びつける
listen()
- ストリームソケットを他のソケットからの接続を受け付ける状態にする
accept()
- 受け付け可能な状態のソケットに対する接続要求を取り出す
connect()
- 他ソケットとの接続を確立する
ソケットについて、ここではごく一部しか紹介出来ないが、非常に多くの事が可能な概念である。
IPCのまとめとしての記事ではこの程度に留まるが、ソケットに関する記事は豊富にあるので必要になればそちらを参照していただきたい。まとめ
それぞれの特徴、長所、短所を見極め、最適なIPCを用いられると便利。
自分の場合、ファイルパス等のやり取りにはPOSIXメッセージキューを用いている。ダラダラと駄文を書き連ねてしまったが、必要に応じてそれぞれ実装のサンプルを含めてまた別でまとめたい。
- 投稿日:2019-12-03T10:47:24+09:00
プロセス間通信
Introduction of Communication
agenda
WHOAMI
IPFactory 1年 @n01e0
普段はLinuxのカーネルモジュールを作ったりしています。WHAT IS IPC
IPCとは Inter Process Communication の略称である。
プロセス間でのデータのやり取りを意味し、Linuxにおいては、様々な種類のIPCが用意されている。
本記事ではそれぞれの軽い紹介程度に留め、実装について詳細な説明は行わない。
各機能のおおまかな特徴を理解し、読者にとっての最適な選択が出来ることを目標としている為である。IPCの分類
IPCはその機能により大きく3つに分類される
- 通信
- プロセス間のデータ通信、交換に関する機構
- 同期
- プロセス、スレッド間の同期に関する機構
- シグナル
- シグナルは特殊で、条件によっては同期にも通信にも用いることが出来る
IPCの仕様
IPCはUNIXの長い歴史の中でいくつかの規格に沿って実装されており、混在している。
主にSystem Vの実装とPOSIXの実装がある
全体的にPOSIXの方が扱いやすくなってはいるが、POSIXのIPCはカーネルバージョン2.6から実装されている為、可搬性には劣る。SYSTEM V IPC と POSIX IPC
System Vにおいて、各IPCのデータ構造は、カーネル空間にあり、
プロセスがIPC資源(セマフォ、メッセージキュー、共有メモリリージョン)を要求した時に動的に生成される。
各IPC資源は固有の識別子を持ち。ユーザーは各IPCをそれとは異なるIPCキーで区別出来る。
この関係はファイルとファイルディスクリプタの関係に似ている。
しかし、ファイル異なる点として、プロセスが明示的に解放しない限り、メモリ上に存在し続ける。
同様の機能を提供するPOSIX IPCがあり、こちらはマルチスレッドセーフな設計になっている。
もう1つの大きな差異としては、POSIXでは各IPCに名前を付けて区別できる点がある。
命名には規則があり、/で始まり、/以外の1文字以上の長さのnull終端の文字列でなければいけない。
仕様に細かな違いはあるが、各IPCの概念で大きく異なるのは各オブジェクト(資源)の管理方法であるIPCの比較
System VとPOSIXの大きな違いとしてIPCオブジェクトの識別子、ハンドラがあり、これらを列挙する。
IPC種別 識別子 ハンドラ パイプ なし ファイルディスクリプタ FIFO パス ファイルディスクリプタ System Vセマフォ System V IPCキー System V IPC ID POSIX 無名セマフォ なし セマフォポインタ POSIX 名前付きセマフォ POSIX IPCパス セマフォポインタ System Vメッセージ System V IPCキー System V IPC ID POSIXメッセージ POSIX IPCパス メッセージキューディスクリプタ System V共有メモリ System V IPCキー System V IPC ID POSIX共有メモリ POSIX IPCパス ファイルディスクリプタ UNIXドメインソケット パス ファイルディスクリプタ インターネットドメインソケット IPアドレス ポート ファイルディスクリプタ 本記事で紹介するLinuxにおけるIPC
PIPE
パイプとは
日常、シェルで生活をしている読者にとっては非常に慣れ親しんだ概念だろう。
シェルにおけるパイプ(|)とは何なのか、改めて簡単に記すと
あるプロセスの出力を別のプロセスの入力につなげる
といった意味になる。
IPCとしてのパイプも同様、データの出力と入力を繋げる為に用いられる事が多い。
パイプのデータ構造について、何かを例に説明しようと思ったが、パイプ以外に良い例が浮かばない。
筒なので、入出力は先入れ先出しとなる。
まとめると、パイプとは単方向の先入れ先出し型データ構造である。実装
unistd.hで定義されているpipe()システムコールは2つのファイルディスクリプタを生成する。
一方は読み出し用、もう一方は書き込み用となる。
これらは、ファイルディスクリプタではあるが、対応するパスは無い。
パイプに書き込まれたデータは、読み出されるまでカーネル内のデータ構造によってバッファリングされる。
通常、空のパイプに対してプロセスが読み込み(read())を行うと、そのパイプにデータが書き込まれるまで、読み込みは停止する。FIFO
類似した機能として
FIFOが存在する。
名前付きパイプとも呼ばれ、また名前の通り先入れ先出しのデータ構造である
パイプと異なる点は、作られるファイルディスクリプタに名前(パス)があるという点くらい。SIGNAL
これもまた、慣れ親しんだ概念だろう。
シグナルもIPCの一種であると言える。
シグナルには多くの種類があるので、一部を例にとって挙げると
SIGHUPSIGINTSIGQUITSIGKILLSIGSEGVなどがある。
シグナルは主に、プロセスに対し何かが発生したことを伝える時、プロセスに特定の動作をさせる時に用いられている。
シグナルの持つ情報量は少なく、通常は番号(種類)以外の情報は持たない。
また、受け取ったシグナルをどう扱うかはプロセス次第である。対応
シグナルへの対応にはいくつかパターンがある
1. 無視
1. 標準設定の動作を実行する
1. シグナルハンドラを呼び出す無視
一部を除き、受け取ったシグナルを無視する事もできる。
無視できない一部のシグナルとは
SIGKILLSIGSTOPであり、これらのシグナルを受け取ったプロセスは、必ず標準設定動作を実行する。
標準設定動作
その標準設定動作とは、名前の通りLinuxにおいて標準で設定されている各シグナルに対する反応である。
プロセスの終了やダンプ、停止、標準で無視が設定されているシグナルもある。シグナルハンドラ
標準設定動作以外にも、
signal()を用いてユーザーが各シグナル毎の対応を定義できる。実装
プロセスがプロセスに対し、シグナルを発行すると、シグナルはカーネルによって受け取られる。
カーネルは対象のプロセスが実行中かどうかを調べ、実行中でなかった場合にはシグナルを保留状態にする。
signal()システムコールは引数にシグナルの種類と対応するシグナルハンドラとなる関数のポインタを持ち、それらを対応づける。SEMAPHORE
セマフォはIPCの分類の中でも、同期機構にあたる。
セマフォの実態は整数値である。
複数プロセスで共有する資源の保護の為、アクセス制御のカウンタとして割り当てられで構成される。
構成
整数型の変数
カウンタとなる。この値が資源の状態(使用可能か否か)を示す
操作待ち状態にあるプロセスのリスト
資源が使用可能になるまで待機しているプロセスのリスト
2つのアトミックなメソッド
セマフォのカウントアップ、ダウンを行う。
セマフォが保護している資源にプロセスがアクセスする時、まず対象資源に紐付けられたセマフォをカウントダウンする。
もしそのセマフォのカウントが負になった場合、プロセスの実行は中断され、リストに加えられる。
資源へのアクセスが終わると、プロセスはセマフォをカウントアップする。
これによりセマフォの値が正になると、リストのプロセスが再開される。実装
セマフォ自身がプロセスの動作を制限する訳ではなく、セマフォに意味を持たせるのはあくまでユーザーである。
また、セマフォは同期機構である為、非常に複雑な操作を必要とする。System V
semget()によりセマフォを作成、または開く。
semop()によってセマフォの操作を行う。POSIX
POSIXでは、セマフォは2種類存在する
- 名前付きセマフォ
- メモリベースドセマフォ(無名セマフォ)名前付きセマフォ
POSIXの他のIPC同様、セマフォに名前を付けて管理出来る。
名前を共有する事で、プロセス間でセマフォを共有するメモリベースドセマフォ
共有メモリにマッピングされる。
名前を持たず、プロセス、スレッド間でメモリの共有によってセマフォを共有する。MESSAGE
IPCメッセージキューは名前の通りキューである。
プロセスによって送信されたメッセージは、他のプロセスが読み込むまでメッセージキューに置かれる。
他のプロセスがメッセージを読み込むと、カーネルはメッセージをキューから削除する。
そのため、プロセス間でのメッセージのやり取りは必ず一対一となる。実装
System V
メッセージとして送信されるデータは、必ずメッセージの優先度を整数値で指定する必要がある。
受信側は、優先度を指定してメッセージを受け取る。
(となると、先入れ先出しではなくなることもあるのでキューと呼んで良いものなのか)
msgget()を用いてキューを取得し、messnd()で送信、msgrcv()で受信する。POSIX
POSIXメッセージキューも名前を付けて管理する。
受信の際、メッセージの優先度を指定する事は出来ない。
最も高い優先度の、最も古いメッセージが読み出される。
mq_open()でキューを開き、mq_sendで送信、mq_receiveで受信を行う。SHARED MEMORY
IPC共有メモリ
名前の通り、共有するメモリ空間に特定のデータ構造を配置する。
また、他のIPCは実行時にユーザー空間からカーネル空間のデータ構造へデータを転送していたのに対し、共有しているメモリ空間へマッピングするだけなのでオーバーヘッドも小さい。
しかし、カーネルが介していないという点には留意すべき問題もある。
複数プロセスが同時にアクセスするのを防ぐ必要性があり、その為には先述のセマフォを用いる事が出来る。実装
System V
shmget()により、共有メモリセグメントを作成、または既存セグメントのIDを取得shmat()により、自プロセスのメモリ空間に共有メモリセグメントをアタッチshmdt()により、デタッチする。アタッチされた共有メモリセグメントはプログラム内の通常のメモリと何ら違いなく扱える。
共有メモリオブジェクトが破棄されるのは、すべてのプロセスがデタッチしshmctl()により削除された時である。POSIX
shm_open()によって共有メモリオブジェクトをオープンする。また、この戻り値はファイルディスクリプタである。- 得られたファイルディスクリプタに対し、
MAP_SHAREDフラグをセットしてmmap()するSOCKET
ソケット。
ソケットはデータの転送方式によって2つに分類でき、
- ストリームソケット
- データグラムソケット
と呼ばれる。
ストリームソケットは名前の通りストリームとして扱え、ファイル等と同様、書き込んだサイズに関わらず任意のバイト数読み取れる。
データグラムソケットはメッセージ等と似ており、データに特定の区切りがあり、読み取りではデータ全体を読み取る必要がある。
また、ソケットのもう一つの分類として、通信先での分類もある
- UNIXドメインソケット
- インターネットドメインソケット
と呼ばれ、
UNIXドメインソケットは同一ホスト内でのアプリケーション間の通信を、インターネットドメインソケットではインターネットプロトコルで接続されたアプリケーション間の通信をサポートしている。実装
ソケットの操作に関するシステムコールは
-socket()
- 新規ソケットを作成する
-bind()
- ソケットをアドレスに結びつける
-listen()
- ストリームソケットを他のソケットからの接続を受け付ける状態にする
-accept()
- 受け付け可能な状態のソケットに対する接続要求を取り出す
-connect()
- 他ソケットとの接続を確立するソケットについて、ここではごく一部しか紹介出来ないが、非常に多くの事が可能な概念である。
IPCのまとめとしての記事ではこの程度に留まるが、ソケットに関する記事は豊富にあるので必要になればそちらを参照していただきたい。まとめ
それぞれの特徴、長所、短所を見極め、最適なIPCを用いられると便利。
自分の場合、ファイルパス等のやり取りにはPOSIXメッセージキューを用いている。ダラダラと駄文を書き連ねてしまったが、必要に応じてそれぞれ実装のサンプルを含めてまた別でまとめたい。
- 投稿日:2019-12-03T07:56:47+09:00
シェルスクリプトについてメモ
シェルスクリプトについてメモ。
シバンについて #!
シェルスクリプトを作成する際は、
冒頭に #! で始まる行を追加する必要がある。これはシバンと呼ばれている。/test.sh#!/bin/bash mkdir test#!/bin/bash という行は、/bin/bashで動かすという宣言をしている
このシェルスクリプトの実行方法は、こちら
./test.shシェルから実行命令を受けたLinuxカーネルが、対象ファイルの先頭を確認して
もし#!があったら、その後に書かれたコマンドを実行するよという流れ実質的には
/bin/bash ./test.shこのようなコマンドラインとして実行される
sourceコマンドでファイルを実行
その他にsourceコマンドを利用して、シェルスクリプトを実行することができる。
source ./test.shsourceコマンドは、指定したファイルの内容をそのままコマンドラインとして実行する。
シバン(#!) が表記されていても、# はコメントアウトとして扱われるので無視される
ちなみにsourceコマンドと同様の意味をもつ、ドットコマンドもある
. ./test.shドットだと、見落としやすいので、sourceコマンドの方がベターかもしれない。
こういう基本はしっかりと抑えたい。
- 投稿日:2019-12-03T02:31:46+09:00
ターミナルで使えるファイラrangerを使ってみる
※本投稿はTechCommit Advent Calendar 2019の2日目の記事です。
はじめに
こんにちは、フリーランスでプログラマーをやってます rattcv と申します。
僕は普段の開発では主にLinuxを使っていて、割とターミナルエミュレータに閉じこもって作業する事が多いんです。
CLI環境において、作業中のディレクトリ上で編集したいファイルを効率よく探す方法は色々あって、最近は「選択的インターフェイス」と呼ばれるジャンルの peco とか fzf 等のツールをシェルと組み合わせて使いこなしている例を良く見かけますし、VimやEmacs等、エディタから使う検索プラグインにも色々と便利なものが揃っていますよね。
上記の様な便利なツール類を上げてる記事とかを見て「スゲー便利そうだなー」と思って試してはみるものの、中々手に馴染まず使うのをやめちゃうのが常だったりします。使いこなせたら凄い効率あがりそうなんですけどね笑それで僕は普段どうしてるかというと、昔っからの慣れで FDclone というMS-DOS用のファイラ"FD"をUnix系OSに移植したファイラをよく使ってます。見た目はこんな感じですね。
これはとても手に馴染んでて、もうしょっちゅう
fdfdって無意識に打っちゃう位多用してますね笑他にCLIで使えるファイラに Midnight Commanderっていうのがあります。良く海外のCLI環境のスクリーンショットでお目にかかりますよね。これは使った事がないので今インストールしてみました笑
日本語化もされてて見た目からして使いやすそうな感じですね!時間があったら試してみたいです。
さて、かなり脱線しましたが、ここからが本題の "ranger" です。
rangerのインストール
ranger っていうCLIファイラはpython製でとても高機能で、Vimキーバンドで使える上にVimの中にも組み込めるっていう話を聞いてて興味があったんで、今回試してみる事にしました。
トライする環境ですが、今この記事書いてるUbuntu Desktopでやろうと思ったんですが色々イジってるうちにrangerの一部機能が使えなくなっちゃったので、持ち歩き用のLinuxネットブックを使います。こんな感じです。~% cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=17.04 DISTRIB_CODENAME=zesty DISTRIB_DESCRIPTION="Ubuntu 17.04"Ubuntuのリポジトリのrangerはバージョンが古いんですが、今は手っ取り早く試したいのでサクッと
aptでインストールしちゃいます。~% sudo apt-get install ranger ffmpegthumbnailer w3m-img xpdf highlight mediainfo atool依存関係も含めてインストールされます。バージョンを確認してみます。
~% ranger --version ranger version: ranger 1.8.1 Python version: 2.7.13 (default, Nov 23 2017, 22:12:08) [GCC 6.3.0]初期設定の為、下記コマンドを打ちます。
~% ranger --copy-config=all上記で
$HOME/.config/ranger配下にデフォルトの設定ファイルが作成されます。
設定ファイルを以下の様に編集します。$HOME/.config/ranger/rc.confset draw_borders true$HOME/.config/ranger/scope.sh# Image preview for video, disabled by default.: video/*) ffmpegthumbnailer -i "$path" -o "$cached" -s 0 && exit 6 || exit 1;; # PDF documents: pdf) try pdftoppm -jpeg -singlefile "$path" "$cached" && mv "$cached.jpg" "$cached" && exit 6 || exit 1;;ここまでrangerを一度起動してみます。
~% rangerこのファイラの真骨頂はVimキーバインド(
HJKL)でどんどんディレクトリに潜っていけて、最終的なファイル選択により一番右側にファイルのプレビューが表示可能な所だと思います。
上記設定によりテキストファイルはSyntaxHighlightがかかった状態で、PDFや各種画像ファイル、動画のサムネイルもプレビュー表示出来てしまいます。
プレビュー表示から更に
L押下で、当該ファイルを適切なアプリケーションで開く事ができます。なかなか優れものですよね。ファイルのアイコン表示を試してみる
僕はターミナルには Cicaフォント を使用する様に設定してますが、このフォントはアイコンフォントを包括しているのでranger上でもファイルにアイコン表示をする事が可能です。
上記のフォントをインストールした状態で、ranger_devicons を導入します。
~% git clone https://github.com/alexanderjeurissen/ranger_devicons.git ~% cd ranger_devicons ~/ranger_devicons% make installこの状態でrangerを起動するとこんな感じになります。
結構イイ感じですよね。
他にもrangerには色々便利な設定がたくさんあるので、以下の参考サイトを参照してみて頂ければと思います。
・ArchWiki - ranger
・CLIファイルマネージャrangerの基本設定
・Rangerを少し試した他のOSでの使用について
MacOSでは
apt-getの代わりにHomebrewを使ってbrewコマンドでUbuntuと同様にインストール出来ると思います(すいません、僕Mac持ってないんですが多分出来ます)。iTrem2の画像表示機能を使ってファイルプレビューする場合は、rc.confをset preview_images_method iterm2に修正すればイケる様です。
Windowsでは、Linuxディストリビューションが使えるWSLとターミナルエミュレータをインストールすればこちらも同様に使用可能です。
WSL&wslttyを導入する記事をこちらに書きましたので、参考にして頂ければと思います。
ただし、WSLではw3m-img(の画像表示用のツールであるw3mimgdisplay)が使えないので画像のプレビューが現状出来ないです。これは頑張れば出来る様になりそうな気がするので、成功しましたらお知らせします笑ではでは、是非是非CLIファイラーの世界で遊んでみてください!
- 投稿日:2019-12-03T01:22:22+09:00
Paiza Cloud で LINE Bot を試してみる
プロトアウトスタジオアドベントカレンダー4発目の記事です!
昨日は @tkyko13 さんの「word2vecの勉強で「word2vecの勉強で「ナダルリバースエボリューション」が再現できるのではないかと思いついたのでやってみた」でした。
Paiza Cloud とは
クラウド開発環境 PaizaCloudクラウドIDE - クラウドIDEでWeb開発!
ブラウザを開くだけでLinuxサーバが使える!
クラウド開発環境PaizaCloudクラウドIDEでは、ブラウザだけでLinuxサーバを操作できます。ファイル操作、テキスト操作、コマンド操作、Webサーバ/DBサーバの立ち上げなど、全てブラウザだけで行えます。 もう、面倒なコマンドでのログイン(ssh)やファイル操作(vim)、ファイルのアップロードは必要ありません。 目の前のコンピュータと同じように、クラウド上のLinuxサーバを操作できます。とのことで、以前、Katacodaで LINE Messaging API Playground (ja) を作った身としては興味があります。
料金表をみてみても1つのサーバーが無料で24時間使えるので、Katacodaよりも長時間使えます。(2019/12/03現在)
サーバーを立ち上げる
Paiza Cloud のアカウント登録をして、まず、Node.jsサーバを立てあげてみましょう。
新規サーバーを押します。
Node.jsをクリックして新規サーバ作成します。
このような形で起動します。
LINE Bot をつくる
1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest - Qiita
こちらの資料をベースに、「1. Botアカウントを作成する」を進めてBotと友達になるところまで進めましょう。
「2. Node.jsでBot開発」からはじめます。
左のメニューのターミナルを押して、ターミナルを起動します。
npm i @line/bot-sdk expressを実行します。
無事インストールされました。
新規ファイルを押して、
server.js ファイルを作成します。
以下をコピー&ペーストしましょう。
server.js'use strict'; const express = require('express'); const line = require('@line/bot-sdk'); const PORT = process.env.PORT || 3000; const config = { channelSecret: '作成したBOTのチャンネルシークレット', channelAccessToken: '作成したBOTのチャンネルアクセストークン' }; const app = express(); app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない) app.post('/webhook', line.middleware(config), (req, res) => { console.log(req.body.events); //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。 if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){ res.send('Hello LINE BOT!(POST)'); console.log('疎通確認用'); return; } Promise .all(req.body.events.map(handleEvent)) .then((result) => res.json(result)); }); const client = new line.Client(config); function handleEvent(event) { if (event.type !== 'message' || event.message.type !== 'text') { return Promise.resolve(null); } return client.replyMessage(event.replyToken, { type: 'text', text: event.message.text //実際に返信の言葉を入れる箇所 }); } app.listen(PORT); console.log(`Server running at ${PORT}`);保存します。
自分のBotとして動くように、Channel SecretとChannel Access Tokenを反映
自分のBotとして動くように、Channel SecretとChannel Access Tokenを反映させます。
1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest - Qiita
の流れに沿ってChannel SecretとChannel Access Tokenをメモしておきます。
左上のファイルツリーから server.js を選択してエディタで編集できるようにします。
const config = { channelSecret: 'channelSecret', channelAccessToken: 'channelAccessToken' };server.jsのこちらを変更します。仮に Channel Secret が ABCDEFGHIJ 、channelAccessTokenが 1234567890 とすると。
const config = { channelSecret: 'ABCDEFGHIJ', channelAccessToken: '1234567890' };と、なります。
ファイルを保存します。
server.jsを動作させてWebhook URLを設定
ターミネルウィンドウで以下のコマンドを打ち込んで起動します。
node server.js起動すると Server running at port 3000 と表示されたらOKです。
公開URL確認
起動すると左のメニューに 3000 というボタンが出来るので、公開URLを確認します。
内部ブラウザが開いてURLが確認できるのでメモしておきましょう。
こちらをLINEの管理画面のメッセージ送受信設定>Webhook URLに反映します。
これで準備完了です。
動かしてみる
実際にLINEでBotを会話してオウム返しを体験しましょう。
LINEで話しかけてみると無事返答されます。
ターミナルを見てみると
サーバーのやり取りも確認できます。
明日の記事は…
@doikatsuyuki さんの「Firebaseを利用した中耳炎診療支援Webアプリの作成 (1.Firebaseの設定~認証方法の追加)」です!




















