- 投稿日:2020-11-30T23:36:50+09:00
Docker上のCentOSだと自作systemdが動かない時の対応方法
どういう状況だってばよ!?
- CentOSで定期実行を実現する為にsystemdを自作したい。
- 実機のCentOSだと自作systemdが動くのに、Docker上のCentOSだとなぜかダメ。
- 具体的にはDocker上だと下記のエラーでこける。
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is downあたいはこんな環境でやってます
この記事は下図のようにWindows10のDocker Desktopをインストール済で、Docker-composeももれなくセットでインストールされている前提になります。
まずはdocker-compose.ymlを新規作成
どこかのフォルダにdocker-compose.ymlという設定ファイルがある訳ではないです。
また、docker-compose.ymlを置く場所はひとまずどこでもよかとです。Docker初心者なので『docker-compose.ymlって設定ファイルどこにあるの…?どこに置かなきゃいけないの…?』なんて右往左往してました…(´・ω・`)
docker-compose.yml ≒ コンテナ作成手順書(指示書) って捉えるといいかな~って思います。
んで、今回は『C:\Users\waokitsune\centos8_systemd_test』というフォルダにdocker-compose.ymlを作成してみました。
docker-compose.ymlの中身
参考サイトさん を参照させてもらいました。
(centosという名前のイメージは既にある前提のymlになります)version: "3.8" services: centos8_systemd_test: image: centos volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro cap_add: - SYS_ADMIN command: /sbin/initPowerShellでDocker-composeにymlを食わせる
PowerShellを起動してまずはdocker-composeが置いてある場所へ行き…
cd C:\Users\waokitsune\centos8_systemd_testdocker-composeコマンドでコンテナ作成。
docker-compose up -dymlを食わせて出来たコンテナを使うぞい
Docker Desktopのダッシュボード開いて、端末起動!
ああ…なんか頭痛が痛いみたいなコンテナ名になっちゃってますね…(´・ω・`)
まずは
ps aux
でプロセスを見てみましょい。
なんか行けそうな気がします。ちなみに自作systemdが動かなかったコンテナの
ps aux
結果はこちら。
テキストファイルを作成するシェルスクリプトファイル『zoi.sh』をルート直下に作成します。
zoi.sh#!/usr/bin/bash touch /zoizoi.txt作ったシェルスクリプトファイルに実行権限を与えてあげます。
chmod 755 /zoi.shそして、『/etc/systemd/system』フォルダーに『zoi.service』ファイルを作成します。
作ったシェルスクリプトをキックするだけの簡単なやつです。zoi.service[Unit] Description=kyoumoitinitigannbaruzoi [Service] Type=simple ExecStart=/zoi.sh [Install] WantedBy=multi-user.target準備ができたので『zoi.service』を起動してみます。
systemctl start zoi.serviceエラー無く終了したっぽいです。
本当か?本当にそうかぁ~?
systemctl status zoi.service
で確認。
白丸なので正常終了っぽいです。
(シェルスクリプトに実行権限与え忘れてサービス起動した痕跡があるのはモアイ教ご愛敬)
ls /
でも確認。
シェルスクリプトによってテキストファイルが作成されてます。OKっす。
無事、Docker上のCentOSで自作systemdを動かせました。
蛇足
docker-compose.ymlがあると『まったく同じ環境をまた作る』が簡単にできて便利だと思いました。
参考サイトさん
バージョン
Windows10 Pro バージョン1909 OSビルド19042.630
Docker Desktop:2.5.0.1(49550) Engine:19.03.13 Compose:1.27.4
PSVersion 5.1.19041.610
CentOS Linux release 8.2.2004 (Core)
- 投稿日:2020-11-30T21:10:56+09:00
Linux ウェルノウンポート
【Linux ウェルノウンポート】
LPIC102 覚えておくべき代表的なウェルノウンポート
20 FTP TCP ファイル転送(データ用)
21 FTP TCP ファイル転送(制御用)
22 SSH TCP リモートホストの遠隔操作(暗号化有り)
23 Telnet TCP リモートホストの遠隔操作(暗号化無し)
25 SMTP TCP 電子メール送信
53 DNS TCP/UDP 名前解決
80 HTTP TCP テキストや画像などのコンテンツの送受信(暗号化無し)
110 POP3 TCP 電子メール受信
143 IMAP TCP 電子メール受信
443 HTTPS TCP テキストや画像などのコンテンツの送受信(暗号化有り)
- 投稿日:2020-11-30T20:52:19+09:00
Linux シェルスクリプト
- 投稿日:2020-11-30T20:37:30+09:00
Linux 特殊なシェル変数
- 投稿日:2020-11-30T20:32:35+09:00
Go言語で作成した実行ファイルをEC2でデーモンとして実行する
概要
Go言語でbuildした実行ファイルをEC2上に配置しdeamon化します。
そうして、EC2の起動時に自動的にGoでビルドしたWebサーバを実行させます。経緯
Go言語+GinでビルドしたWebサーバをEC2上で構築していたのですが、
EC2の起動時に自動実行されなかったのでいろいろと試した結果、デーモン化しinit.dで自動起動させました。1 ビルドした実行ファイルのデーモン化
ディレクトリ /etc/systemd/system/サービス名.service [Unit] Description=説明文 [Service] User=root Group=root WorkingDirectory=ディレクトリ ExecStart=ディレクトリ/実行ファイル名 Restart=always KillMode=process [Install] WantedBy=multi-user.targetサービスの確認
systemctl status サービス名.service
systemctl start サービス名.service
systemctl stop サービス名.service上記でサービスの起動が出来たらデーモン化は完了です。
2. init.dでサービスの自動起動を設定
ディレクトリ /etc/int.d/app_start --------------init.d 内容------------------------- #!/bin/sh # chkconfig: 2345 99 10 # description: deamon wakeup scrupt case "$1" in start) date >> /home/user/start.txt echo "start!" >> /home/user/app_start.log sudo sh /home/user/scripts/application_start_server.sh ;; stop) echo date >> /home/user/app_stop.log sudo sh /home/user/scripts/application_stop_server.sh ;; *) break ;; esacapplication_start_server.sh の部分は直接コマンドを書いても良いですし、
今回はシェルスクリプトを実行させました。
(サービスの起動・停止時に時間をファイルに出力しています。)3 確認
EC2を再起動しサービスが正常に起動していれば完了です。
所感
インスタンスの再起動は物理マシンの起動と挙動が違うので、
その辺りが原因でバッチ処理ではうまく動かなかったのだと考えています。
- 投稿日:2020-11-30T20:22:05+09:00
個人開発でも気軽に使える Copy Protection サービスをつくりました
この記事は個人開発 Advent Calendar 2020 6日目の記事です。
昨日は @yakipudding さんによる「Reactで作成したポートフォリオサイトをNextに移行した」でした。
改良後のデザインがおっしゃられるとおりとてもスッキリしていて、センスの良さが本当に羨ましかったです。はじめに
作った理由はこちらに書いたとおりです
3ヶ月ぐらいでできるかと見積もっていたのですが実際はリリースまで6ヶ月もかかってしまい、自分の effort estimation の精度に自信をなくして落ち込んだりもしたのですが、単に私の productivity が普通のエンジニアの半分ぐらいしかなかっただけなのかもしれない1と気をとりなおして今は元気な私はソフトウェア工学屋崩れ2の野良犬です
(U^ω^)関係ないのですが Software Engineering at Google 読んでて、エンピリカルなソフトウェア工学屋さんの言ういわゆる effort の事を一貫して endeavor って呼んでるのが珍しい言い方3だなとおもいました
こちらでは RPi の話しか書かなかったのですが、RPi4 だけでなく Linux でも Mac でも使える汎用5のコピープロテクションですので、皆様もこちらに書いたみたいな目にあったりされましたら(されないように)使っていただければと思いまして、老爺心ながら使い方をご紹介させていただきます次第です
サービスの紹介
Koshitno はSansi ライブラリと共にアプリケーションのコピープロテクションを提供するクライアント - サーバ型の No license file な application anti-piracy サービスです
コピープロテクションって一般にライセンス定義ファイルとかライセンスキーとかを使ってアプリケーションを unauthorized なコピーから保護するものなのですが、ストレージがむき出しな RPi だとそれが弱点になると考え、それらを使わないで実現するためにクライアント-サーバ型で実装しました
クライアント-サーバ型であることで、ネットワークに接続していないスタンドアロンなアプリでは利用できないというネガティブな副作用があるのですが、逆に、扱いが煩わしく失敗すると事故の原因になりかねないライセンスファイルをつかわないですむのでお気軽お手軽というポジティブな副作用も生じております。世の中捨てる神あれば拾う神あり、人生全て塞翁が馬ということなのでございましょう
koshinto と sansi のコピープロテクションの仕組み
こちらに書いたとおりなのですが、sansi ライブラリはユーザーがダウンロードする時からその内部にアプリケーションの束縛条件を一意に表す ID (以下、Bind_id と呼びます)をバイナリで埋め込んであります
sansi ライブラリの提供する confirm() 関数は、呼ばれると各種の環境情報(デバイスのシリアルナンバー、IP アドレス、Mac アドレス等)を収集して、Bind_id と一緒に Koshinto に送信します
koshinto サーバは sansi から送信された情報と、内部に保存するアプリケーションの束縛条件をチェックして、OK/NG の返答をセキュアに返します
koshinto からの OK/NG の応答を confirm() は戻り値でアプリケーションにします
以上、アプリケーションは起動時に confirm() を呼んで、戻り値が NG だったら exit するように一文を入れるだけで copy protection の実装が完了するわけでございます。これは簡単!
この仕組自体の anti-tamper についてはこちらに紹介いたしました
使用例
サンプルアプリケーション
10秒間の秒読みを行う、シチュエーションによってはとても practical なアプリケーションです
main.simple.c/* * 10 second countdown, copy guarded by sansi * * @author Dr. Takeyuki UEDA * @copyright Copyright© Atelier UEDA 2020 - All rights reserved. */ #include <stdio.h> // for printf #include <unistd.h> // for seep void tenseccount(); int main(){ tenseccount(); return 0; } void tenseccount(){ int i; printf("start 10 second countdown\n"); for (i=10; i>0; i--){ printf("%d\n",i); sleep(1); } printf("0!\n"); }Practical なので悪意の第三者による意図せぬコピー、著作権侵害をふせぐために sansi を組み込んで保護しましょう
sansi の組み込み
main.simple.c/* * 10 second countdown, copy guarded by sansi * * @author Dr. Takeyuki UEDA * @copyright Copyright© Atelier UEDA 2020 - All rights reserved. */ #include "sansi.h" // for sansi libraries #include <stdio.h> // for printf #include <unistd.h> // for seep void tenseccount(); int main(){ if (ok_confirmed == confirm(NULL, NULL, NULL)){ printf("OK\n"); } else { printf("NG\n"); return -1; } tenseccount(); return 0; } void tenseccount(){ int i; printf("start 10 second countdown\n"); for (i=10; i>0; i--){ printf("%d\n",i); sleep(1); } printf("0!\n"); }追加したのは以下の2点で
- 8行目: sansi.h のインクルード
- 16-21行目: アプリの最初に confirm() を呼び、戻り値が ok_confirmed でなければ異常終了サンプルプロジェクトの clone
完成品はこちらにございますので、git clone して
MacBook-Air:tmp takeyuki$ git clone https://github.com/UedaTakeyuki/sansi_examples.git
sansi_examples/c フォルダに移動してください
MacBook-Air:tmp takeyuki$ cd sansi_examples/cls してみるといろいろなファイルがあります
MacBook-Air:c takeyuki$ ls README.md compile.sh main.c main.simple.c sansi.h左からそれぞれ README、 compile スクリプト、別のサンプルの main.c (本稿ではつかいません)、先程紹介した main.simple.c、そして sansi のヘッダーファイルです
ここでは紹介しませんが、C アプリの他に go, python, bash の組込例も用意させていただきました
go は cgo で sansi をリンクする例をご紹介させていただきました。vlang も同様にできるように思っているのですけどまだ試せていません。どなたか pull req いただければ感謝の言葉もございません
python は nuitka でコンパイルして strip すること、bash は shc とかでバイナリ化する前提ですsansi のダウンロード
Koshinto にログインして Home から [Binds]-[All] を選択してください
アカウントを作った直後だと、一つだけですが Bind がすでにあるのでこれを選択して
メニューから Sansi library Download を開き
アプリケーションのターゲットに合わせてライブラリをダウンロードしてください
ダウンロードしたライブラリを先程 git clone したプロジェクトにコピーしてください
MacBook-Air:c takeyuki$ cp /Users/takeyuki/Downloads/libsansi_ZbPdGoGyrNkQ_mac_v1.1.o . MacBook-Air:c takeyuki$ ls README.md main.c compile.sh main.simple.c libsansi_ZbPdGoGyrNkQ_mac_v1.1.o sansi.hアプリケーションのコンパイル
コンパイルスクリプトの使い方は
MacBook-Air:c takeyuki$ ./compile.sh -h Usage: ./compile.sh [-h][-c][-g][-m][-o obj] [source] [libsansi] [source]: compiling source file, default is 'main.sample.c' [libsansi]: path for linking 'libsansi….o', default is found it in cwd automatically [-h]: show this usage and exit [-c]: compile for linux by clang [-g]: compile for linux by gcc, this is default [-m]: compile for mac by clang [-o obj] set compiled object file name, default is a.out MacBook-Air:c takeyuki$ ./compile.sh -mデフォルトで main.sample.c をコンパイルして、デフォルトで a.out をつくります。デフォルトで sansi ライブラリをよしなにさがしてくれるので便利です
Mac 用のコンパイルの場合
Mac 用のコンパイルであることを指示する -m を指定する必要があります
bash:
MacBook-Air:c takeyuki$ ./compile.sh -m
source = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_mac_v1.1.o
compiler = clang
obj = a.out
compiling…
尚、sansi は OpenSSL に依存するのですが、Mac だと OpenSSL がインストールされていないかもしれません。その旨のエラーがでた場合はインストールしてください
Linux 用のコンパイルの場合
Linux の場合はなにも指定する必要がありません
pi@raspberrypi:~/sansi_examples/c $ ./compile.sh source = main.simple.c libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o compiler = gcc obj = a.out compiling…-c を指定すると gcc の代わりに clang でコンパイルします
pi@raspberrypi:~/sansi_examples/c $ ./compile.sh -c source = main.simple.c libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o compiler = clang obj = a.out compiling…例1. アプリケーションを Mac のシリアル番号に束縛する
Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです
アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください1. 事前に取得した key の値に直接束縛する場合
Koshinto に戻って Bind の [Keys] を開きます
調べておいた Mac のシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします
Status を開き、Binding を選択して右下の UPDATE をクリックします
Mac に戻って a.out がブロックされずに実行できているのが確認できます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
2. sansi が取得して送信してきた値から選択して束縛する場合
Mac に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずですMacBook-Air:c takeyuki$ ./a.out NG
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします
keys を開くと値が送信されてきています
Platform Serial Number の lock を✓して右下の UPDATE をクリックします
Status は Bind Waiting から Bind Requesting に遷移しています
Status を Binding に変更します
変更したら右下の UPDATE をクリックして変更を反映させます
Mac に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合
アプリケーションが最初に起動された Mac のシリアルナンバーに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます現在の Status は Not Active なので
Auto Bind Waiting に変更します
Mac に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします
keys の値は sansi が収集して送信してきた値に更新されていて、Platform Serial Number も更新されています
Status は Binding に遷移しています
例2. アプリケーションを RaspberryPi の SDカードのシリアルIDに束縛する
Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです
アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください1. 事前に取得した key の値に直接束縛する場合
Koshinto に戻って Bind の [Keys] を開きます
調べておいた SD カードのシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします
Status を開き、Binding を選択して右下の UPDATE をクリックします
Raspberry Pi に戻って a.out がブロックされずに実行できているのが確認できます
pi@raspberrypi:~/sansi_examples/c $ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
2. sansi が取得して送信してきた値から選択して束縛する場合
Raspberry Pi に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずですpi@raspberrypi:~/sansi_examples/c $ ./a.out NG
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします
keys を開くと値が送信されてきています
SD Card Serial ID の lock を✓して右下の UPDATE をクリックします
Status は Bind Waiting から Bind Requesting に遷移しています
Status を Binding に変更します
変更したら右下の UPDATE をクリックして変更を反映させます
Raspberry Pi に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます
pi@raspberrypi:~/sansi_examples/c $ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合
アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます現在の Status は Not Active なので
Auto Bind Waiting に変更します
Raspberry Pi に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします
keys の値は sansi が収集して送信してきた値に更新されていて、SD Card Serial ID も更新されています
Status は Binding に遷移しています
例3. アプリケーションを Linux Server の Global IP address に束縛する
Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです
アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください1. 事前に取得した key の値に直接束縛する場合
Koshinto に戻って Bind の [Keys] を開きます
調べておいた Global IP address
を Global IP に入力して lock を✓し、右下の UPDATE をクリックしますStatus を開き、Binding を選択して右下の UPDATE をクリックします
Linux に戻って a.out がブロックされずに実行できているのが確認できます
ueda@amfortas:~/sansi_examples/c$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
2. sansi が取得して送信してきた値から選択して束縛する場合
Linux に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずですueda@amfortas:~/sansi_examples/c$ ./a.out NG
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします
keys を開くと値が送信されてきています
Global IP の lock を✓して右下の UPDATE をクリックします
Status は Bind Waiting から Bind Requesting に遷移しています
Status を Binding に変更します
変更したら右下の UPDATE をクリックして変更を反映させます
Linux に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます
ueda@amfortas:~/sansi_examples/c$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合
アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます現在の Status は Not Active なので
Auto Bind Waiting に変更します
Linux に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます
ueda@amfortas:~/sansi_examples/c$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします
keys の値は sansi が収集して送信してきた値に更新されていて、Global IP も更新されています
Status は Binding に遷移しています
詳説
1. Bind の5種類の状態と、アプリケーションを Bind する3通りの方法
正常な Bind のステータスは以下の5つのどれかになります。各ステータスで confirm() の通知を受けた際の戻り値と、koshinto 内の bind の key と status の変化を表にまとめました
status return koshinto の bind の key koshinto 内の bind の status Not Active 常に ng_comfirmed 変化なし 変化なし Bind Waiting 常に ng_comfirmed confirm からの値で更新 Bind Requestingに遷移 Bind Requesting 常に ng_comfirmed 変化なし 変化なし Auto Bind Waiting 常に ok_comfirmed confirm からの値で更新 Binding Binding confirm からの値によって ng_comfirmed またはok_comfirmed 変化なし 変化なし Not Active が、Bind が使われていない状態です
Binding が、アプリケーションが束縛されている状態ですアプリケーションを Bind する方法は3種類あって
- キーの値を設定してロックし、状態を Binding に変更
- 状態を [Bind Waitingに変更]して sansi からの confirm()を待つ。bind の key が更新され、状態が [Bind Requesting] に変わるので、適切な key を選んでロックし、状態を [Binding]に変更
- 適切な key を選んでロックしてから状態を [Auto Bind Waitingに変更]して sansi からの confirm()を待つ。key の値が更新されて自動的に [Bind]状態になる
束縛したい key の値(今の場合は Mac のシリアルナンバー)を事前に知っていて(「このマックについて」で確認済で)、その値を使って束縛する場合に 1. の手順になります。調べるのってめんどくさかったり typo があったりすると思うので後述の 2. や 3. の手順をお薦めいたしますが、Bind の状態の推移はシンプルに次のようになります
[Not Active] -> [Bind]
束縛したい key の値を知らない、もしくは自分で調べるのがめんどくさいので sansi に任せたい場合、sansi が送ってくる値を確認して問題がなければその値に束縛する場合が 2. の手順になります。遷移は
[Not Active] -> [Bind Waiting] -> [Bind Requesting] ->[Bind]
確認せずに自動的にその環境に束縛するのが 3. の手順になります。遷移は
[Not Active] -> [Auto Bind Waiting] -> [Binding]
related works
こちらを参照いただければ幸いです
名前の由来
Koshinto と Sansi の名前の由来はこちらを参照賜われれば至福の至に存じます次第です
結び
長々と書いてしまい本当にどうもすみません、今は謹んで反省しております次第です、無駄に長生きした年寄りの話が無駄に長いのは相応というものでございますれば、エンジニアの情けで許してくだされ/(^o^)\
references
- Raspberry Pi のアドベントに記事を書きました
- セキュリティのアドベントに Koshinto 自身の anti-tamper について書きました
- Koshinto Docs Koshinto のドキュメント
- Koshinto Koshinto サービスの入り口
- Sansi_Example アプリケーション への Sansi の組み込み方の言語毎の解説とサンプル。現在、c, go, python, bash の例を用意しています
- 庚申信仰 蛇足ながら Wikipedia
明日は
明日は@azukisiromochiさんによる「アプリ名『焼き鳥』事件 ???」です!私は前日なのでメンションもらって限定公開の頃から読ませて頂いてたのですが、正直、ものすごくおもしろい、ためになるお話なんですよ!お楽しみに!
もともと RPi だけの、それも SD CARD と Board の ID だけのつもりだったのに、つい NIC を追加したら Mac や Linux 一般にも欲がでて、という途中からの仕様追加を個人開発なのにやりまくったのも悪かったかもしれません ↩
無駄に工学博士持ってます。せっかく博士なんだから、何時の日かガッチャマンみたいな自分の戦隊が欲しいと日々思いつつなんか作ってます。わるもんでもいいけど。それか怪盗グルーとミニヨンみたいな仲間とか ↩
タイトルに反してそういう人達へのネガティブな感情が前提にあるのかと読んでて勘ぐりました ↩
Raspberry Pi 以外の各種 IoT ボードも Linux ベースであれば IP address や MAC IDに束縛することで利用可能です。ボード固有のIDのへの束縛も対応していきたく、リファレンスボードの donation を募集してます ↩
Windows は持ってないので、開発に使える PC の donation を募集しています ↩
- 投稿日:2020-11-30T20:22:05+09:00
個人開発でも気軽に使える Copy Protection のサービスをつくりました
この記事は個人開発 Advent Calendar 2020 6日目の記事です。
昨日は @yakipudding さんによる「Reactで作成したポートフォリオサイトをNextに移行した」でした。
改良後のデザインがおっしゃられるとおりとてもスッキリしていて、センスの良さが本当に羨ましかったです。はじめに
作った理由はこちらに書いたとおりです
3ヶ月ぐらいでできるかと見積もっていたのですが実際はリリースまで6ヶ月もかかってしまい、自分の effort estimation の精度に自信をなくして落ち込んだりもしたのですが、単に私の productivity が普通のエンジニアの半分ぐらいしかなかっただけなのかもしれない1と気をとりなおして今は元気な私はソフトウェア工学屋崩れ2の野良犬です
(U^ω^)関係ないのですが Software Engineering at Google 読んでて、エンピリカルなソフトウェア工学屋さんの言ういわゆる effort の事を一貫して endeavor って呼んでるのが珍しい言い方3だなとおもいました
こちらでは RPi の話しか書かなかったのですが、RPi4 だけでなく Linux でも Mac でも使える汎用5のコピープロテクションですので、皆様もこちらに書いたみたいな目にあったりされましたら(されないように)使っていただければと思いまして、老爺心ながら使い方をご紹介させていただきます次第です
サービスの紹介
Koshitno はSansi ライブラリと共にアプリケーションのコピープロテクションを提供するクライアント - サーバ型の No license file な application anti-piracy サービスです
コピープロテクションって一般にライセンス定義ファイルとかライセンスキーとかを使ってアプリケーションを unauthorized なコピーから保護するものなのですが、ストレージがむき出しな RPi だとそれが弱点になると考え、それらを使わないで実現するためにクライアント-サーバ型で実装しました
クライアント-サーバ型であることで、ネットワークに接続していないスタンドアロンなアプリでは利用できないというネガティブな副作用があるのですが、逆に、扱いが煩わしく失敗すると事故の原因になりかねないライセンスファイルをつかわないですむのでお気軽お手軽というポジティブな副作用も生じております。世の中捨てる神あれば拾う神あり、人間万事塞翁が馬ということなのでございましょう
koshinto と sansi のコピープロテクションの仕組み
こちらに書いたとおりなのですが、sansi ライブラリはユーザーがダウンロードする時からその内部にアプリケーションの束縛条件を一意に表す ID (以下、Bind_id と呼びます)をバイナリで埋め込んであります
sansi ライブラリの提供する confirm() 関数は、呼ばれると各種の環境情報(デバイスのシリアルナンバー、IP アドレス、Mac アドレス等)を収集して、Bind_id と一緒に Koshinto に送信します
koshinto サーバは sansi から送信された情報と、内部に保存するアプリケーションの束縛条件をチェックして、OK/NG の返答をセキュアに返します
koshinto からの OK/NG の応答を confirm() は戻り値でアプリケーションにします
以上、アプリケーションは起動時に confirm() を呼んで、戻り値が NG だったら exit するように一文を入れるだけで copy protection の実装が完了するわけでございます。これは簡単!
この仕組自体の anti-tamper についてはこちらに紹介いたしました
使用例
サンプルアプリケーション
10秒間の秒読みを行う、シチュエーションによってはとても practical なアプリケーションです
main.simple.c/* * 10 second countdown, copy guarded by sansi * * @author Dr. Takeyuki UEDA * @copyright Copyright© Atelier UEDA 2020 - All rights reserved. */ #include <stdio.h> // for printf #include <unistd.h> // for seep void tenseccount(); int main(){ tenseccount(); return 0; } void tenseccount(){ int i; printf("start 10 second countdown\n"); for (i=10; i>0; i--){ printf("%d\n",i); sleep(1); } printf("0!\n"); }Practical なので悪意の第三者による意図せぬコピー、著作権侵害をふせぐために sansi を組み込んで保護しましょう
sansi の組み込み
main.simple.c/* * 10 second countdown, copy guarded by sansi * * @author Dr. Takeyuki UEDA * @copyright Copyright© Atelier UEDA 2020 - All rights reserved. */ #include "sansi.h" // for sansi libraries #include <stdio.h> // for printf #include <unistd.h> // for seep void tenseccount(); int main(){ if (ok_confirmed == confirm(NULL, NULL, NULL)){ printf("OK\n"); } else { printf("NG\n"); return -1; } tenseccount(); return 0; } void tenseccount(){ int i; printf("start 10 second countdown\n"); for (i=10; i>0; i--){ printf("%d\n",i); sleep(1); } printf("0!\n"); }追加したのは以下の2点で
- 8行目: sansi.h のインクルード
- 16-21行目: アプリの最初に confirm() を呼び、戻り値が ok_confirmed でなければ異常終了サンプルプロジェクトの clone
完成品はこちらにございますので、git clone して
MacBook-Air:tmp takeyuki$ git clone https://github.com/UedaTakeyuki/sansi_examples.git
sansi_examples/c フォルダに移動してください
MacBook-Air:tmp takeyuki$ cd sansi_examples/cls してみるといろいろなファイルがあります
MacBook-Air:c takeyuki$ ls README.md compile.sh main.c main.simple.c sansi.h左からそれぞれ README、 compile スクリプト、別のサンプルの main.c (本稿ではつかいません)、先程紹介した main.simple.c、そして sansi のヘッダーファイルです
ここでは紹介しませんが、C アプリの他に go, python, bash の組込例も用意させていただきました
go は cgo で sansi をリンクする例をご紹介させていただきました。vlang も同様にできるように思っているのですけどまだ試せていません。どなたか pull req いただければ感謝の言葉もございません
python は nuitka でコンパイルして strip すること、bash は shc とかでバイナリ化する前提ですsansi のダウンロード
Koshinto にログインして Home から [Binds]-[All] を選択してください
アカウントを作った直後だと、一つだけですが Bind がすでにあるのでこれを選択して
メニューから Sansi library Download を開き
アプリケーションのターゲットに合わせてライブラリをダウンロードしてください
ダウンロードしたライブラリを先程 git clone したプロジェクトにコピーしてください
MacBook-Air:c takeyuki$ cp /Users/takeyuki/Downloads/libsansi_ZbPdGoGyrNkQ_mac_v1.1.o . MacBook-Air:c takeyuki$ ls README.md main.c compile.sh main.simple.c libsansi_ZbPdGoGyrNkQ_mac_v1.1.o sansi.hアプリケーションのコンパイル
コンパイルスクリプトの使い方は
MacBook-Air:c takeyuki$ ./compile.sh -h Usage: ./compile.sh [-h][-c][-g][-m][-o obj] [source] [libsansi] [source]: compiling source file, default is 'main.sample.c' [libsansi]: path for linking 'libsansi….o', default is found it in cwd automatically [-h]: show this usage and exit [-c]: compile for linux by clang [-g]: compile for linux by gcc, this is default [-m]: compile for mac by clang [-o obj] set compiled object file name, default is a.out MacBook-Air:c takeyuki$ ./compile.sh -mデフォルトで main.sample.c をコンパイルして、デフォルトで a.out をつくります。デフォルトで sansi ライブラリをよしなにさがしてくれるので便利です
Mac 用のコンパイルの場合
Mac 用のコンパイルであることを指示する -m を指定する必要があります
bash:
MacBook-Air:c takeyuki$ ./compile.sh -m
source = main.simple.c
libsansi = libsansi_ZbPdGoGyrNkQ_mac_v1.1.o
compiler = clang
obj = a.out
compiling…
尚、sansi は OpenSSL に依存するのですが、Mac だと OpenSSL がインストールされていないかもしれません。その旨のエラーがでた場合はインストールしてください
Linux 用のコンパイルの場合
Linux の場合はなにも指定する必要がありません
pi@raspberrypi:~/sansi_examples/c $ ./compile.sh source = main.simple.c libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o compiler = gcc obj = a.out compiling…-c を指定すると gcc の代わりに clang でコンパイルします
pi@raspberrypi:~/sansi_examples/c $ ./compile.sh -c source = main.simple.c libsansi = libsansi_ZbPdGoGyrNkQ_arm_v1.1.o compiler = clang obj = a.out compiling…例1. アプリケーションを Mac のシリアル番号に束縛する
Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです
アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください1. 事前に取得した key の値に直接束縛する場合
Koshinto に戻って Bind の [Keys] を開きます
調べておいた Mac のシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします
Status を開き、Binding を選択して右下の UPDATE をクリックします
Mac に戻って a.out がブロックされずに実行できているのが確認できます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
2. sansi が取得して送信してきた値から選択して束縛する場合
Mac に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずですMacBook-Air:c takeyuki$ ./a.out NG
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします
keys を開くと値が送信されてきています
Platform Serial Number の lock を✓して右下の UPDATE をクリックします
Status は Bind Waiting から Bind Requesting に遷移しています
Status を Binding に変更します
変更したら右下の UPDATE をクリックして変更を反映させます
Mac に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合
アプリケーションが最初に起動された Mac のシリアルナンバーに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます現在の Status は Not Active なので
Auto Bind Waiting に変更します
Mac に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします
keys の値は sansi が収集して送信してきた値に更新されていて、Platform Serial Number も更新されています
Status は Binding に遷移しています
例2. アプリケーションを RaspberryPi の SDカードのシリアルIDに束縛する
Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです
アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください1. 事前に取得した key の値に直接束縛する場合
Koshinto に戻って Bind の [Keys] を開きます
調べておいた SD カードのシリアルナンバーを Platform Serial Number に入力して lock を✓し、右下の UPDATE をクリックします
Status を開き、Binding を選択して右下の UPDATE をクリックします
Raspberry Pi に戻って a.out がブロックされずに実行できているのが確認できます
pi@raspberrypi:~/sansi_examples/c $ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
2. sansi が取得して送信してきた値から選択して束縛する場合
Raspberry Pi に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずですpi@raspberrypi:~/sansi_examples/c $ ./a.out NG
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします
keys を開くと値が送信されてきています
SD Card Serial ID の lock を✓して右下の UPDATE をクリックします
Status は Bind Waiting から Bind Requesting に遷移しています
Status を Binding に変更します
変更したら右下の UPDATE をクリックして変更を反映させます
Raspberry Pi に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます
pi@raspberrypi:~/sansi_examples/c $ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合
アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます現在の Status は Not Active なので
Auto Bind Waiting に変更します
Raspberry Pi に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます
MacBook-Air:c takeyuki$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします
keys の値は sansi が収集して送信してきた値に更新されていて、SD Card Serial ID も更新されています
Status は Binding に遷移しています
例3. アプリケーションを Linux Server の Global IP address に束縛する
Koshinto に戻って Bind のステータスを確認すると Not Active になっているはずです
アプリケーションを Bind する方法は以下の3通りがあります
- 直接、値を入力して Bind
- sansi が取得してきた値を確認して Bind
- sansi が取得してきた値に自動的に Bind正常な Bind のステータスは5通りあって、上記の3つの方法によってステータスの遷移がかわります。詳細については
こちらを参照ください1. 事前に取得した key の値に直接束縛する場合
Koshinto に戻って Bind の [Keys] を開きます
調べておいた Global IP address
を Global IP に入力して lock を✓し、右下の UPDATE をクリックしますStatus を開き、Binding を選択して右下の UPDATE をクリックします
Linux に戻って a.out がブロックされずに実行できているのが確認できます
ueda@amfortas:~/sansi_examples/c$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
2. sansi が取得して送信してきた値から選択して束縛する場合
Linux に戻り、先程コンパイルした a.out を実行します
結果は NG になりますが、sansi が取得したMac の環境の各種値が Koshinto に送信されて Bind に反映されているはずですueda@amfortas:~/sansi_examples/c$ ./a.out NG
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン1(グルグルみたいな奴)を一度クリックします
keys を開くと値が送信されてきています
Global IP の lock を✓して右下の UPDATE をクリックします
Status は Bind Waiting から Bind Requesting に遷移しています
Status を Binding に変更します
変更したら右下の UPDATE をクリックして変更を反映させます
Linux に戻って a.out を実行してみると、今度は正常に起動して10秒の秒読みが実行されます
ueda@amfortas:~/sansi_examples/c$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
3. 何を key にするか決めておいて、sansi が送信してきた値に自動的に束縛する場合
アプリケーションが最初に起動された Raspberry Pi に装着されている SD カードのシリアルIDに自動的に束縛することにします
keys を開いて Platform Serial Number の lock を✓し、右下の UPDATE をクリックして変更を反映させます現在の Status は Not Active なので
Auto Bind Waiting に変更します
Linux に戻って a.out を実行してみると、初回から正常に起動して10秒の秒読みが実行されます
ueda@amfortas:~/sansi_examples/c$ ./a.out OK start 10 second countdown 10 9 8 7 6 5 4 3 2 1 0!
現在の Bind の値を Koshinto からブラウザに反映させるために、Bind の右下のフローティング・アクション・ボタン(グルグルみたいな奴)を一度クリックします
keys の値は sansi が収集して送信してきた値に更新されていて、Global IP も更新されています
Status は Binding に遷移しています
詳説
1. Bind の5種類の状態と、アプリケーションを Bind する3通りの方法
正常な Bind のステータスは以下の5つのどれかになります。各ステータスで confirm() の通知を受けた際の戻り値と、koshinto 内の bind の key と status の変化を表にまとめました
status return koshinto の bind の key koshinto 内の bind の status Not Active 常に ng_comfirmed 変化なし 変化なし Bind Waiting 常に ng_comfirmed confirm からの値で更新 Bind Requestingに遷移 Bind Requesting 常に ng_comfirmed 変化なし 変化なし Auto Bind Waiting 常に ok_comfirmed confirm からの値で更新 Binding Binding confirm からの値によって ng_comfirmed またはok_comfirmed 変化なし 変化なし Not Active が、Bind が使われていない状態です
Binding が、アプリケーションが束縛されている状態ですアプリケーションを Bind する方法は3種類あって
- キーの値を設定してロックし、状態を Binding に変更
- 状態を [Bind Waitingに変更]して sansi からの confirm()を待つ。bind の key が更新され、状態が [Bind Requesting] に変わるので、適切な key を選んでロックし、状態を [Binding]に変更
- 適切な key を選んでロックしてから状態を [Auto Bind Waitingに変更]して sansi からの confirm()を待つ。key の値が更新されて自動的に [Bind]状態になる
束縛したい key の値(今の場合は Mac のシリアルナンバー)を事前に知っていて(「このマックについて」で確認済で)、その値を使って束縛する場合に 1. の手順になります。調べるのってめんどくさかったり typo があったりすると思うので後述の 2. や 3. の手順をお薦めいたしますが、Bind の状態の推移はシンプルに次のようになります
[Not Active] -> [Bind]
束縛したい key の値を知らない、もしくは自分で調べるのがめんどくさいので sansi に任せたい場合、sansi が送ってくる値を確認して問題がなければその値に束縛する場合が 2. の手順になります。遷移は
[Not Active] -> [Bind Waiting] -> [Bind Requesting] ->[Bind]
確認せずに自動的にその環境に束縛するのが 3. の手順になります。遷移は
[Not Active] -> [Auto Bind Waiting] -> [Binding]
related works
こちらを参照いただければ幸いです
名前の由来
Koshinto と Sansi の名前の由来はこちらを参照賜われれば至福の至に存じます次第です
結び
長々と書いてしまい本当にどうもすみません、今は謹んで反省しております次第です、無駄に長生きした年寄りの話が無駄に長いのは相応というものでございますれば、エンジニアの情けで許してくだされ/(^o^)\
references
- Raspberry Pi のアドベントに記事を書きました
- セキュリティのアドベントに Koshinto 自身の anti-tamper について書きました
- Koshinto Docs Koshinto のドキュメント
- Koshinto Koshinto サービスの入り口
- Sansi_Example アプリケーション への Sansi の組み込み方の言語毎の解説とサンプル。現在、c, go, python, bash の例を用意しています
- 庚申信仰 蛇足ながら Wikipedia
明日は
明日は@azukisiromochiさんによる「アプリ名『焼き鳥』事件 ???」です!私は前日なのでメンションもらって限定公開の頃から読ませて頂いてたのですが、正直、ものすごくおもしろい、ためになるお話なんですよ!お楽しみに!
もともと RPi だけの、それも SD CARD と Board の ID だけのつもりだったのに、つい NIC を追加したら Mac や Linux 一般にも欲がでて、という途中からの仕様追加を個人開発なのにやりまくったのも悪かったかもしれません ↩
無駄に工学博士持ってます。せっかく博士なんだから、何時の日かガッチャマンみたいな自分の戦隊が欲しいと日々思いつつなんか作ってます。わるもんでもいいけど。それか怪盗グルーとミニヨンみたいな仲間とか ↩
タイトルに反してそういう人達へのネガティブな感情が前提にあるのかと読んでて勘ぐりました ↩
Raspberry Pi 以外の各種 IoT ボードも Linux ベースであれば IP address や MAC IDに束縛することで利用可能です。ボード固有のIDのへの束縛も対応していきたく、リファレンスボードの donation を募集してます ↩
Windows は持ってないので、開発に使える PC の donation を募集しています ↩
- 投稿日:2020-11-30T17:53:10+09:00
はじめてのnlコマンド
nlコマンドはテキストデータに行番号を付加する機能を持つ、便利なコマンドラインユーティリティです。ほとんどのUnix系環境では、特別なソフトウェアをインストールをすることなく最初から使うことができるコマンドです。この記事では、はじめて
nl
を触る人でも気軽に試せるよう基本的な使い方を説明します。nlコマンドができること
nl
ができることは「テキストデータに行番号をふる」ことです。それ以上でも以下でもありません。コマンドの機能としてはそれだけですが、行番号をふることに関して様々な要求を満たすためのオプションを持っています。そして他のコマンドと組み合わせることで、その用途は「行番号をふる」という枠を越えて広がっていきます。nlコマンドの使い方
基本的な使い方
例えば、JR上野東京ライン北行(宇都宮線・高崎線)の駅名が記載された「utl-kita」という名前のテキストファイルがあるとします。ファイルの中身をそのまま標準出力に表示する
cat
を使うと次のようになります。$ cat utl-kita 東京 上野 尾久 赤羽 浦和 さいたま新都心 大宮このテキストファイル「utl-kita」に
nl
を使用した場合、以下のような出力になります。$ nl utl-kita 1 東京 2 上野 3 尾久 4 赤羽 5 浦和 6 さいたま新都心 7 大宮これで
nl
によって行の先頭に行番号が付加されたことが確認できたと思います。標準入出力の利用
引数を指定してファイルから読み込む以外にも、標準入力から直接データを受け取ることができます。また、標準入力から受け取ることをより明示的にするために、
-
という特殊な引数も用意されています。標準入出力と|
(パイプ)を利用することで、様々なコマンドを組み合わせることができます。さきほどの例は、
cat
とnl
を組み合わせて以下のように実行しても同じ結果になります。$ cat utl-kita | nl 1 東京 2 上野 3 尾久 4 赤羽 5 浦和 6 さいたま新都心 7 大宮パイプを使えばいくつでもコマンドをつなげることができます。以下の例では、
yes
によって出力される「y」にnl
が行番号を付加し、head
が先頭3行だけを切り取って標準出力に表示しています。$ yes | nl | head -n 3 1 y 2 y 3 yリダイレクトとファイル
行番号を付加したデータをファイルに保存するには、
>
(リダイレクト)を使って出力するファイルを指定します。$ nl utl-kita > numbered_utl-kita $ cat numbered_utl-kita 1 東京 2 上野 3 尾久 4 赤羽 5 浦和 6 さいたま新都心 7 大宮これでファイルに保存することができました。残念ながらリダイレクトで元のファイルへの上書き保存はできません。ファイルが消失するので、試す場合は覚悟を持って試しましょう。
$ nl utl-kita > utl-kita $ cat utl-kita $ wc utl-kita 0 0 0 utl-kitaリダイレクトで読み込むファイルと同じファイルに出力した結果、データが消失していることがわかります。
wc
は文字数をカウントするコマンドで、出力の3つの0 0 0
は、左から行数、単語数、バイト数を表します。参考までに元のテキストファイルに対してwc
を実行したときの結果は以下になります。$ wc utl-kita 7 7 64 utl-kita $ wc numbered_utl-kita 7 14 113 numbered_utl-kita詳しくは説明しませんが、上書き保存をするにはmoreutilsというコマンドユーティリティに含まれるspongeコマンドを利用する方法などがあります。
補足
サンプルの
utl-kita
ファイルは、以下のテキストをプロンプトに貼り付ければ簡単に作成することができます。cat <<EOF >utl-kita 東京 上野 尾久 赤羽 浦和 さいたま新都心 大宮 EOF
- 投稿日:2020-11-30T10:18:18+09:00
Postfixメモ
deferredキューに滞留しているメールが再送を何日で諦めるかはこの設定値で決まる。
以下は5日の場合$ postconf | grep -i lifetime bounce_queue_lifetime = 5d maximal_queue_lifetime = 5d滞留メールを見る # postqueue -p 個別にメールをHOLDする # postsuper -h キューID HOLD中のメールをキューに入れ直す(キューIDが変わる) # postsuper -r キューID HOLDキューにあるメールを全て再送する # postsuper -H ALL
- 投稿日:2020-11-30T02:07:35+09:00
tshark: The file to which the capture would be saved ( filename ) could not be opened: Permission denied. の対応法
実現したいこと
[vagrant@localhost ~]$ pwd /home/vagrant [vagrant@localhost ~]$ id uid=501(vagrant) gid=501(vagrant) groups=501(vagrant),10(wheel) [vagrant@localhost ~]$ [vagrant@localhost ~]$ sudo tshark -i enp0s8 -w testcap_`date +%Y-%m-%d_%H-%M-%S`.pcap Running as user "root" and group "root". This could be dangerous. Capturing on 'enp0s8' tshark: The file to which the capture would be saved ("testcap_2020-11-30_01-56-22.pcap") could not be opened: Permission denied. [vagrant@localhost ~]$ [vagrant@localhost ~]$ [vagrant@localhost ~]$ sudo su - 最終ログイン: 2020/11/30 (月) 01:52:42 JST日時 pts/1 [root@localhost ~]# [root@localhost ~]# pwd /root [root@localhost ~]# id uid=0(root) gid=0(root) groups=0(root) [root@localhost ~]# [root@localhost ~]# sudo tshark -i enp0s8 -w testcap_`date +%Y-%m-%d_%H-%M-%S`.pcap Running as user "root" and group "root". This could be dangerous. Capturing on 'enp0s8' tshark: The file to which the capture would be saved ("testcap_2020-11-30_01-56-38.pcap") could not be opened: Permission denied. [root@localhost ~]# [root@localhost ~]# getenforce Disabled [root@localhost ~]#root権限で実行しているのに上記のようにエラーが出てパケットキャプチャした結果をファイルに保存できない。パケットキャプチャー結果をファイルに保存したい。
実行コマンド
$ sudo mkdir -p /opt/capfile $ sudo tshark -i enp0s8 -w /opt/capfile/testcap_`date +%Y-%m-%d_%H-%M-%S`.pcap/rootディレクトリ および /homeディレクトリ(登録されているユーザー) 以外に作成する
補足
- 忘れるからメモ
情報源
- 投稿日:2020-11-30T01:35:35+09:00
wiresharkで特定のHTTP Request Method(例えばGET、POST)のみ表示する
実現したいこと
wiresharkのFilter機能で特定のHTTP Request methodのみを表示させたい。
例えば、POSTのみを表示させたいだったり、GETリクエストのみを表示させたい場合に利用する。実行コマンド
HTTPリクエストメソッド GETの場合
http.request.method == "GET"Filterツールバーに上記のように入力する
HTTPリクエストメソッド POSTの場合
http.request.method == "POST"Filterツールバーに上記のように入力する
補足
HTTPリクエストメソッド GETで特定のパラメータのみ表示する場合
http.request.uri == "/?num=5"Filterツールバーに上記のように入力する
使い所(個人用のメモです...)
- デバッグ用途に使っています。フロントのHTTPサーバーからアプリケーションサーバー(例えばwsgiサーバーなど)へのリクエストを確認する。
情報源
- フィルタ画面を適当に入力してたらなんか出てきた
- https://musclehunter.blogspot.com/2015/09/wiresharkurl.html