それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Deiban/Exim4を設定して、gmailで通知メールを送出する。

2022-09-01 追記

Gmailの場合は「アプリパスワード」か「XOAUTH2」に対応させないと、SMTP/IMAPが使えない。

アプリパスワードは手軽だが、認証がめんどくさくなる諸刃の剣

なので、XOAUTH2が出来るように調べた→ https://takuya-1st.hatenablog.jp/entry/2022/03/14/181637

exim4 → XOAUTH2のPostix → 世界 と転送するのがマシだと思う。

メールの設定はめんどくさい→ exim4 で解決

SMTPリレーとかSMTP Outbound port Blocking 25 ( OBP 25 ) だとかさ、めんどくさいんですよね。理解できない人に、「○○が必要で」などと説明するのもめんどくさい。

実は、メール送信は細かい設定や説明を抜きにして簡単に使うことができる。

exim4 を使って localhost:25 宛に送れば外部のSMTPで送信することができる

Gmail 経由で送信する。

というわけで、一番手っ取り早くて、無料で確実なのが Gmail のアカウントを作ってそこから創出するわけですよ。

Debian/Exim4 でGmail経由で送信

DebianだとPostfixではなくExim4が使われていて、これが軽量で、最低限のことは十分にできるので、Exim4でほとんど十分。

Postfix でやる場合

Postfix ではいぜんやったので そちらのログがある

OBP25でもあきらめない。自宅サーバーでPostfixでスパム判定させずメールをリレーで送る方法: gmail の smtp を使った例 - それマグで!

用意するもの

Exim4の確認

exim4 が入っていることを確認する。

# sudo dpkg --list exim4

exim4 の再起動などの方法を確認

systemd 経由の起動状態を確認

sudo systemctl status exim4

systemd 経由で再起動などを確認

sudo systemctl reload exim4
sudo systemctl stop exim4
sudo systemctl start exim4

exim4 の設定反映はコレでもいける

sudo update-exim4.conf

/etc/exim4/update-exim4.conf.conf

設定を以下のようにする。

#  dc_eximconfig_configtype='local'
dc_eximconfig_configtype='smarthost'
dc_other_hostnames='pizero'
dc_local_interfaces='127.0.0.1 ; ::1'
dc_readhost=''
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets=''
# -dc_smarthost=''
dc_smarthost='smtp.gmail.com::587'
CFILEMODE='644'
dc_use_split_config='false'
dc_hide_mailname=''
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'

ポイントは。次の通り。 :: コロンが2つなのはそういうものです。ミスタイプではありません。

dc_smarthost='smtp.gmail.com::587'

メールアカウントの設定

/etc/exim4/passwd.client

## Gmail アカウント
gmail-smtp.l.google.com:my_name@example.com:my_password
smtp.google.com:my_name@example.com:my_password
*.google.com:my_name@example.com:my_password
gmail-smtp-msa.l.google.com:my_name@example.com:my_password
smtp.gmail.com:my_name@example.com:my_password

パスワードをちょっとだけ保護する。

もっとこう、暗号化したり出来たらいいんだけど。 せめて一般ーザーにはパスワード読めないようにしておく

sudo chown root:Debian-exim /etc/exim4/passwd.client
sudo  chmod 640 /etc/exim4/passwd.client

あとはリロードしてテストする

リロード

sudo update-exim4.conf

テスト

メールが送信できるかテストする。

サンプルメールの作成

sendmail を毎回書くのはめんどくさいので、サンプルメールを作っておくことにします。

cat - >  sample-mail.txt
To:takuya@example.com
Subject: Hello, From pizero

Hi, can you see me ?

サンプルメールの送信

cat sample-mail.txt | sendmail -i -t 

crontab の送信先を変える

exim4 を使ってローカル転送をしてる場合は mailto を設定するとcrontab のメールがSMTP経由で届くようになる。

MAILTO=takuya@example.com

ローカル転送をする

ローカル転送を設定する必要がある

/etc/aliases

root:takuya
takuya: takuya+alias@example.com

/etc/email-addresses

takuya: takuya+from@example.com

ローカル転送の確認

takuya@:~$ exim -brw takuya@localhost
  sender: takuya+from@example.com
    from: takuya+from@example.com
      to: takuya@localhost
      cc: takuya@localhost
     bcc: takuya@localhost
reply-to: takuya+from@example.com
env-from: takuya+from@example.com
  env-to: takuya@localhost

このようにして、どのようにメールが転送されていく確認しておきましょう。

Gmail にブロックされることがある。

全く最近はお節介が過ぎてめんどくさい。

SMTP に直接ログインしようとすると less secure だと言われて怒られるので、分かった分かった。その機能オフにしてくれ。オプトアウトしなくちゃいけない。そもそもなにも設定してない時点でオプトインになってるのが面倒なんだが

手作業でファイルを更新するよりdpkg-reconfigureを使う方法もある。

dpkg-reconfigureを使うとログが残りにくくてめんどくさいんですが、マニュアルにするにはこっちのほうが「ウケ」がいいかもしれないですね。

初期設定画面を起動

sudo dpkg-reconfigure exim4-config

初期設定画面のダイアログ形式でちまちま入れていく

ここだけ入れておく

あとは、お好きなようにいれる。 dpkg-reconfigure が終了したら。/etc/exim4/passwd.client を編集する。

個人的な設定メモ

私は、以下のように設定した。

これでGmail経由で通知できる

sendmail 通知が出来るなら、あとは

  • crontab の通知
  • 再起動の通知
  • ジョブ終了の通知
  • ハードウェアの故障・異常の通知

など各種の通知をメールで受けれて便利ですね。

panic log がずっと送出される。

地味にめんどくさかったのがこのパニックログを消す方法

2019-01-01 15:35:09 socket bind() to port 25 for address ::1 failed: Cannot assign requested address: daemon abandoned

これは、私がサーバーのIPv6を止めて以来ずっと定期的に送られてくる。

実はこれ、過去のパニックログが残っていてログローテートしないことが原因らしい。マジすか exim4

/etc/exim4/update-exim4.conf.conf

# before
# dc_local_interfaces='127.0.0.1; ::1'
# after 
dc_local_interfaces='127.0.0.1'

設定を削除した後に、exim4を再起動

sudo update-exim4.conf
sudo service exim4 restart

これで新しいログは出なくなるが、古いパニック・ログが残存しているとそれを送ってくる。

なので、古いログを削除する必要がある。

sudo rm   /var/log/exim4/paniclog

2017-03-22 追記

ローカル配送と、Gmailのメッセージについて追記した。

2019-07-28 追記

「exim4 設定」でキーワードマッチしなかったので、キーワードを見直し

paniclog について記述を追加

参考資料

2020-01-11

GoogleGmailやアレコレを変えたのでこの設定を見直した

gmail と gsuite で若干の差異があるみたい。

iPhoneのSafariがパスワードを確実に学習するには

iOSSafariがパスワードを保存しないことがある。

なんでかずっと考えてたけど、よく考えたらパスワード保存のダイアログの発動条件を思い出したら、form.submit だったかなぁと考えて、保存させる方法に気づいた。SafariのAddonで解決させるしか無いかなと思ってたんだけど。結構にシンプルな解決方法で行けそう。

ドコモIDもちゃんと保存された

f:id:takuya_1st:20170303165429p:plain:w400

WEBページ側のボタンではなく、キーボードを押す

[f:id:takuya_1st:20170303170147p:plain:w250f:id:takuya_1st:20170303170150p:plain:w250

HTML側のボタンはなぜか、JSでアレコレ( xmlhttp や 隠しform ) されてることが多くログインを学習させないことが多いので、キーボード側からSubmitする。

それでも駄目なら Macとつなぐ

それでも駄目なら、iPhoneMacを繋いで、SafariのDevコンソールから、form.submit()ですねぇ。

こんな感じ?

var form = document.createElement('form');
var text = document.createElement('input');
text.value = 'userid'
var pass = document.createElement('input');
pass. setAttribute('type','password')
pass.value = 'my_pass'
form.insertAdjacentElement('beforeend',text)
form.insertAdjacentElement('beforeend',pass)
form.submit()

form[action]先は適当でも学習したり*1する。

もしくは、PCのパスワードをKeychain同期で持っていくしか無い。ああ不便すぎる。

ログインID学習禁止とかいつまでやるんだろうか。

iOS で共有パソコンっていうのも頭悪い話だし。いいかげんセキュリティ関連のテスト項目や実装項目から外してほしいんだけどなぁ。パスワードを学習しない方が、ずっとセキュリティ・コストだよ。キーチェーンは比較的安全なのにな。

*1: たぶん、送信元ページと結果URLが変わってて 200ok が返ってるのが条件だと思う。なので同一ドメインで適当なURLに飛ばせばいい、ログイン前だと殆どのベージでリダイレクト掛かるからコレは楽

Swiftをshebang指定でシェルスクリプト起動!?linuxでも

面白げな記事を見つけました。

新・OS X ハッキング! (166) 開発者でなくても「Swift」は便利に使える | マイナビニュース

#!/usr/bin/swift で swift が起動するというのです。

試してみる。Xcode は入っているので、ターミナルから試してみます。

バージョン確認
takuya@Desktop$ swift --version
Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1)
Target: x86_64-apple-macosx10.9
takuya@Desktop$

Macで実行してみる

シェルスクリプトとしてSwift を実行してみる。sample.swift ファイルつくって shebang いれて、実行権限をいれる感じですね。

ファイル作って

sample01.swift
#!/usr/bin/swift

import Foundation

let task = Process()


task.launchPath = "/usr/bin/find"
task.arguments = ["."]
task.launch()

task.waitUntilExit()

chmod して

chmod a+x ./sample01.swift

実行

takuya@~$ cd .Trash/
takuya@.Trash$ ~/Desktop/sample01.swift
.
./89-09kotudoro.xls

おおお /usr/bin/find が実行された。 これはシェルスクリプトの代替に pythonruby 使わなくて幸せに慣れそう。node / swift で書くことが出来る。やったね。

どうせならLinuxでも動かしてみる

うちの Debian jessie で swift を動かしてみる。

実験した環境

takuya@:swift$ cat /etc/debian_version
8.6
takuya@:swift$ lsb_release -a
LSB Version:    core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch:core-4.1-amd64:core-4.1-noarch:cxx-3.0-amd64:cxx-3.0-noarch:cxx-3.1-amd64:cxx-3.1-noarch:cxx-3.2-amd64:cxx-3.2-noarch:cxx-4.0-amd64:cxx-4.0-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-3.1-amd64:desktop-3.1-noarch:desktop-3.2-amd64:desktop-3.2-noarch:desktop-4.0-amd64:desktop-4.0-noarch:desktop-4.1-amd64:desktop-4.1-noarch:graphics-2.0-amd64:graphics-2.0-noarch:graphics-3.0-amd64:graphics-3.0-noarch:graphics-3.1-amd64:graphics-3.1-noarch:graphics-3.2-amd64:graphics-3.2-noarch:graphics-4.0-amd64:graphics-4.0-noarch:graphics-4.1-amd64:graphics-4.1-noarch:languages-3.2-amd64:languages-3.2-noarch:languages-4.0-amd64:languages-4.0-noarch:languages-4.1-amd64:languages-4.1-noarch:multimedia-3.2-amd64:multimedia-3.2-noarch:multimedia-4.0-amd64:multimedia-4.0-noarch:multimedia-4.1-amd64:multimedia-4.1-noarch:printing-3.2-amd64:printing-3.2-noarch:printing-4.0-amd64:printing-4.0-noarch:printing-4.1-amd64:printing-4.1-noarch:qt4-3.1-amd64:qt4-3.1-noarch:security-4.0-amd64:security-4.0-noarch:security-4.1-amd64:security-4.1-noarch
Distributor ID: Debian
Description:    Debian GNU/Linux 8.6 (jessie)
Release:    8.6
Codename:   jessie

公式サーバーから swift を持ってくる

ubuntu 14 のものが動いた

wget https://swift.org/builds/swift-3.0.2-release/ubuntu1404/swift-3.0.2-RELEASE/swift-3.0.2-RELEASE-ubuntu14.04.tar.gz \
| tar zxvf - 

REPL でコマンドラインを起動する

Linuxで動きそうなので、せっかくなので対話インターフェースで起動してみる。

./swift-3.0.2-RELEASE-ubuntu14.04/usr/bin/swift

動かす

takuya@:swift$ ./swift-3.0.2-RELEASE-ubuntu14.04/usr/bin/swift
Welcome to Swift version 3.0.2 (swift-3.0.2-RELEASE). Type :help for assistance.
  1> import Foundation
  2> print("Hello Swift Linux")
Hello Swift Linux
  3>

ええ。。。Foundationもあるの。カーソルで戻るなどで若干改行がおかしくなったりするけど問題なさそう。

スクリプトとして実行してみる

ファイル作って

takuya@:swift$ cat  - > sample.swift
#!/home/takuya/swift/swift-3.0.2-RELEASE-ubuntu14.04/usr/bin/swift

import Foundation

let filelist = Task()
filelist.launchPath = "/bin/sh"
filelist.arguments = ["-c", "ls -lS ./"]
filelist.launch()
filelist.waitUntilExit()

実行権限をつけて

takuya@:swift$ chmod 755  sample.swift

実行した

takuya@:swift$ ./sample.swift
合計 115764
-rw-rw-r-- 1 takuya takuya 118528337 12月 14 10:49 swift-3.0.2-RELEASE-ubuntu14.04.tar.gz
drwxrwxr-x 3 takuya takuya      4096  3月  3 16:12 swift-3.0.2-RELEASE-ubuntu14.04
-rwxr-xr-x 1 takuya takuya       226  3月  3 16:34 sample.swift
-rw-rw-r-- 1 takuya takuya       177  3月  3 16:17 test.swift

ちょっと面食らうのが NSTaskProcess でもなく Task だったところかな。

面白い

ちょっとしたシェルスクリプトのファイル操作なども swift で書くことが出来る。プログラミング言語として整ってるので期待したい。Swiftのちょっとしたコードをぱぱっと試せるのは便利ですね。関数の使い方をちょっと試すのに便利そう。内部でコンパイルしてるんだろうけど、、、、

MacのFinderなどプログラムを強制終了・再起動

Mac のFinderを再起動

Finderを再起動するのに

killall Finder

ですが、メニューからも出来るんです。

左上のメニューから再起動する

  • Finder.app を選ぶ
  • Finderを選んだ状態で左上  メニュー
  • Shift キーを押す

f:id:takuya_1st:20170301183207p:plain

なんでも強制終了出来る

finderに限らず、選択したアプリケーションをなんでも強制終了出来る。

f:id:takuya_1st:20170301183723p:plain

うん、手軽で便利ですね。

php のフォークと強制終了

単純なフォーク

<?php
$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child:", $pid);
  exit;
}

実行結果

pcntl_wait($status); //Protect against Zombie children
var_dump("END :", $pid);

       \-+= 48201 takuya -bash
         \-+= 49054 takuya php fork.php
           \--- 49055 takuya php fork.php

49054 から 49055 が生えた

2個フォークした場合

<?php
$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child:", $pid);
  exit;
}

$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child1");
  exit;
}
pcntl_wait($status); //Protect against Zombie children
var_dump("END :", $pid);

実行中の状態

         \-+= 48802 takuya php fork.php
           |--- 48803 takuya php fork.php
           \--- 48804 takuya php fork.php

48802 から 48803, 48804 が生えた

フォークからさらにフォークした場合。

子プロセスから更に子プロセス、つまり孫プロセスを起動したら

<?php
$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child:", $pid);
  exit;
}

$pid = pcntl_fork();
if ($pid == -1) {
  die('could not fork');
} else if ($pid) {
  // we are the parent
} else {
  // we are the child
  sleep(10);
  var_dump("We are the child1");
  exit;
}
pcntl_wait($status); //Protect against Zombie children
var_dump("END :", $pid);

この場合、子プロセスが孫より先に死ぬので孫が迷子になってしまう。孤児としてrootプロセスに引き取られる。

なのでちゃんと管理をしなくてはいけない。

fork 先でしっかり終了させる。つまり単純な作業に限定するとか、終了待ちをきちんとする。など

また、子プロセスが生成した子プロセスを見るには再帰して ps -o pid,ppid ax で 子プロセスpidを ppid にもつ孫を探すことになるかもしれない。

fork の注意点

fork を使う前に POSIX fork を知る必要がある。

fork のタイミングでメモリがコピーされますが、リソース(ファイルディスクリプタ)はコピーされると面倒が起きます。MySQLやHTTPなどのコネクションもfd(ファイルディスクリプタ)になってたりするので、fork 先でコネクションしないとエラーになることがある。

fork のコスト

fork するとメモリがコピーされるので、若干負荷が大きい操作になる。そこから先は別プロセスになるので、fork後のメモリの変更(変数の値変更)は別になる。

平行世界が作成されるイメージ

fork の利点

php でも時間がかかる処理は fork 先に任せて、メインは違うことに集中するなどと出来る。

コストは高いが、ジョブを待つだけの メインがあってジョブが来たら fork して仕事をやらせるみたいなことも出来る。

シグナルハンドラ

fork した両方のプロセスでシグナルをハンドリングするには、pcntl_signal_dispatchを入れてあげないといけないみたい

pcntl_signal_dispatch();の代わりに declare(ticks=1) を入れることで解決はしますが、tick を小さくするとパフォーマンスに影響します。

Ctrl+C(SIGINT)を押しても即時反応しない場合とかもdispatchまでいったんキューに入るからだと思います。

pcntl_signal_dispatch はその名前の通り、シグナルキューをそれぞれのハンドラに振り分けるものですね。

<?php


// signal handler function
function sig_handler($signo)
{
  echo "SIGNAL:" . $signo."\n";
  switch ($signo) {
    case SIGTERM:
      echo 'cactch SIGTERM'."\n";
      // handle shutdown tasks
      exit;
      break;
    case SIGINT:
      echo 'cactch SIGINT'."\n";
      exit;
    case SIGHUP:
      echo 'cactch SIGHUO'."\n";
      break;
    case SIGUSR1:
      echo "Caught SIGUSR1...\n";
      echo 'pid:'.posix_getpid();
      echo ' ppid:'.posix_getppid();
      break;
    default:
      echo 'default';
  }

}


pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT,  "sig_handler");
pcntl_signal(SIGHUP,  "sig_handler");
pcntl_signal(SIGUSR1, "sig_handler");

pcntl_signal_dispatch();

while (1){

  $a = 0;
  echo 'pid:'.posix_getpid()."\n";

  $pid = pcntl_fork();

  if ($pid===0) {
    // we are the child
    pcntl_signal_dispatch();
    sleep(5);
    var_dump("We are the child:", $pid);
    exit;
  }else{
    pcntl_signal_dispatch();

  }

  pcntl_wait($status); //Protect against Zombie children
  var_dump("waiting is end :", $pid);

}

linux の プロセス管理についてのおすすめ本

Linux のexecコールやfork とプロセス管理がしっかり分かる本だった。

参考資料

pcntl - What's the relation between declare(ticks) and a signal handler in php - Stack Overflow

http://qiita.com/ngyuki/items/a2b9d6d3011528d3becd

スクリーンセーバに表示される時計を大きくしたい

スクリーンセーバーに表示される時計を大きくしたいなと

macOSで打ち合わせ中に、どんどんアイディアが発散して、収拾つかなくなる人が多い。なので、時間を表示しながら打ち合わせで、あっさり解決するんじゃないかと。会議室に時計がなかったり、ホテルや貸し会議室や、外などで時計がないときに話が終わらないよーみたいなときに、無言プレッシャーをかけるのが、時計を置いておいて、チラチラみるという行為。なので時計があると嬉しい。

アイディアソンやハッカソンなどで時間を表示したいときにも便利、時計アプリとかだと画面焼けそうだからつねに写真が動くスクリーンセーバーがいいよね。

時計をMacの画面に常に表示しておいたらいいよね。

いちいち、なにかスクリーンセーバーを探してくるのもめんどくさいので、少し頭をひねった。

出来た

f:id:takuya_1st:20170227153522j:plain

スクリーンの拡大を設定する

コントロール・キー+マウス・スクロールで任意の場所を拡大できるようにする。

f:id:takuya_1st:20170227153518p:plain

右下30%を拡大する

f:id:takuya_1st:20170227154958p:plain

できた。

iTerm2 でwitch などキーボードのリマップなどが効かない問題

iTerm2 でキーボードのリマップなどが効かない問題が出た

すごくハマった。なのでメモ。

Karabiner やwitch や hyperSwtich あと Contexts なども一切使えなくなって、もうどうしようかみたいに頭を抱えてた

option+tab / ctrl + tab なども駄目

一切のスイッチャーが使えなくなって、 macOS デフォルトのAppSwiterしか手がなくなって辛かった。

アプリの切り替えではなく、ウインドウの切り替えがしたいんだ。

ここを一時的にオンオフして回避する。

f:id:takuya_1st:20170227140747p:plain

iTerm2 のマニュアルにあった。

iTerm2 > Secure Keyboard Entry

When this is enabled, the operating system will prevent other programs 
running on your computer from being able to see what you are typing.
 If you're concerned that untrusted programs might try to steal your passwords,
you can turn this on, but it may disable global hotkeys in other programs.

キーボードのりマッピングは、セキュリティ的に危ない?

まぁ、常駐しているアプリに側にキーボードの盗聴やリマップを許可してしまうのはたしかにやばいけれど。 「許可したアプリ」にキーボードのリマップ許可するものがないのは辛いな。Sierraだともっとキツイんだろうな。。。怖いな。

macOS が不自由すぎてやばい。

Hyper switch メインで使ってたから完全にハマった

過去にもハマってた

ターミナルがキーボードのカスタマイズとかちあう時の対策 - それマグで!

node.js の node コマンドが CTRL+R効かない

node で ctrl+R が効かない。

ctrl+r 無いと不便だよね。irb は数年前に解決した、sqlite3 は先日解決させた。 今度はnode もなんとかしたいなと調べた。

sqlite のときのように readline ライブラリで解決するかと思ったら解決しない。

node REPL をどうするか問題

node の REPL を使うことで、アレコレできるようになっていて、今まで見たものと根本的に設計思想が違うようですね。

const repl = require('repl');

rlwrap を使うと楽になるようで。

rlwrap / readline wrapper を使って nodeで reverse-increment-search 何とかすると動くようです。

alias node="env NODE_NO_READLINE=1 rlwrap node"

無理やり動いた

rlwrap で無理やり動いた

takuya@~$ node
> const takuya={}
undefined
> takuya
{}
(reverse-i-search)`':

rlwrap は何をしているのか。

rlwrap はヒストリファイルを別途作って rlwrap が node にptsをパイプしてる感じ。

もし、readline非対応でもコレを使ったら強引に使えるようになるので便利そう。

参考資料

https://nodejs.org/api/repl.html

https://github.com/hanslub42/rlwrap

https://linux.die.net/man/1/rlwrap

brewで入れたsqlite3でCTRL+Rが効かない!

brew で入れた sqlite で reverse-i-search が使えない

reverse-i-search ってすごく便利で CTR+Rでヒストリをインクリメンタル検索出来る機能なんだけど。動かなかった。

色々調べたら、GNU Readline ではなく、Mac 標準添付のeditline(?) を使ってるとか。mac がGNU readline を外したのでこういうことになってるようだ。

readlineを有効にしてコンパイルし直す

brew install readline

このREADLINEを参照先にして、 SQLiteをインストールし直す。

CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" brew reinstall  sqlite3
takuya@~$ sqlite3
-- Loading resources from /Users/takuya/.sqliterc
SQLite version 3.17.0 2017-02-13 16:02:40
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
(reverse-i-search)`':

動いた!安心。

RMagick が入らない: gem install rmagick error:Mac OS X/brew に rmagickをインストールする決定版

RMagick を久しぶりに使おうとしたら・・・

インストール

gem install rmagick 

はい、エラー。extconf.rb ってほんと良く詰まるわ 色々調べたら、Rmagick が imagemagick 7 に非対応だった。

brew unlink imagemagick
brew install imagemagick@6
brew link --force imagemagick@6

コレをやったあとに

インストール

gem install rmagick 

動いた

takuya@~$ irb
>>
>> require 'rmagick'
=> true
>>

インストール後に元に戻す

brew unlink imagemagick@6
brew link imagemagick

原因はこの辺

include のフォルダ構造が ImagMagick7 から変わってるのに対応できてない。

checking for wand/MagickWand.h... no
"/usr/bin/gcc -E -I/Users/takuya/.rbenv/versions/2.3.3/include/ruby-2.3.0/x86_64-darwin15 -I/Users/takuya/.rbenv/versions/2.3.3/include/ruby-2.3.0/ruby/backward -I/Users/takuya/.rbenv/versions/2.3.3/include/ruby-2.3.0 -I.  -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=32 -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=32 -I/usr/local/Cellar/imagemagick/7.0.5-0/include/ImageMagick-7  -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=32 -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=32 -I/usr/local/Cellar/imagemagick/7.0.5-0/include/ImageMagick-7  conftest.c -o conftest.i"

強引に ln -s しても駄目だった フォルダ構造併せたら行けるかなと思ったけど、関数の参照でエラーになったのでもうめんどくさい。

cd /usr/local/Cellar/imagemagick/7.0.5-0/include/ImageMagick-7
ln -s MagickWand wand
ln -s MagickCore magick
# リンクしても、参照型が合わなくてコンパイルエラーになってた。

なので、ImageMagick6をbrew でインストールして強制link するしかなかった。

まぁRMagickの対応待ちになるんだろうかね。怖い怖い

2017-05-17

若干更新

OSX El Capitan / macOS Sierra からパーミッションの復旧がなくなった

タイトルのとおりです。

El capitan / Sierraからパーミッションの復旧がなくなってSIP( system integrity protection )がメインになってる。

たまに、SIP オフで使ったりするので、パーミッションの復旧がなくなるとめんどくさいことになってる。

パーミッション復旧ツールを見つけた

RepairPermissions V3 – Now supports repairing permissions on macOS Sierra | FireWolf Pl.

導入と実行

ぱぱっとダウンロードしてハッシュチェックします。

curl -LJO http://www.firewolf.science/download/715/
name=( RepairPermissions*.zip )
if [[ ! -f  $name ]] ;then
  exit;
fi
echo $name
hash=$(md5sum RepairPermissions*.zip | awk '{print $1}' );
[[  $name =~ _(.*).zip  ]] ; echo $? ; echo ${BASH_REMATCH[1]};
[[ ${BASH_REMATCH[1]} == $hash ]]; echo $?
unzip $name
chmod +x RepairPermissions

実行

実行してパーミッションを修正する。

sudo RepairPermissions / 

実行結果

RepairPermissions - Verify and repair permissions of an entire volume
Copyright (C) 2016 FireWolf @ FireWolf Pl. All Rights Reserved.

Current OS: OS X El Capitan 10.11.6 (15G1217)
 Target OS: OS X El Capitan 10.11.6 (15G1217)

  Info:  SIP Allow Unrestricted File System [ENABLED]
  Info:  RepairPermissions will repair permissions on /
  Info:  This will take some time. Grab a cup of coffee and be patient.
  Info:  RepairPermissions is running in Normal Mode.
  Info:  Intel(R) Core(TM) i5-4258U CPU @ 2.40GHz 2C4T
  Info:  Available Processors: 4; Will use up to 4 processor(s).
Status:  [ULTRAFAST] Doing some wolf's magics...    Progress: 59.78% [\]
Status:  [ULTRAFAST] Doing some wolf's magics...    Progress: 89.95% [|]
Status:  [ULTRAFAST] Doing some wolf's magics...    [COMPLETED]

これで、多少のことを気にせずにガンガン行けるね。

まぁSIPをオンにすれば戻るんだろうけど。

画像の比較をしてズレがないか調べる

image magick で画像の比較をすることが出来る。

画像の比較をするにはいろいろな方法がある。

  • 目で見てわかりやすい→WEBや校正用
  • 機械的に見てわかりやすい→ダイアログなどプログラムのテスト
  • 画像におおきな影が出る→動体検出

等と大きく分けて使い分けることになると思います。とくに機械学習などで自動化の事前処理に役立つと思います。

元画像1: 1.png

f:id:takuya_1st:20170224170950p:plain:w300

元画像2 : 2.png

f:id:takuya_1st:20170224170905p:plain:w300

機械的に色を見るやり方

比較方法

compare の場合

compare -metric AE 1.png 2.png compare-AE.png

metric による違い

AEとPSNR の違いを見ておきます。キャプチャ画面はAEの方が良さそう。

AE の例

f:id:takuya_1st:20170224171416p:plain:w300

PSNR の例

f:id:takuya_1st:20170224171433p:plain:w300

metric 一覧を見るには

takuya@Desktop$ compare -list metric
AE
Fuzz
MAE
MEPP
MSE
NCC
PAE
PHASH
PSNR
RMSE

composite で画像の差分を見る

compsite コマンドで画像を合成して、差分を明確することも出来る。同じ色だと黒色になる。スクリーンキャプチャに向いてる。

composite -compose difference 1.png 2.png compsite-diff.png

composite diffrence の例

f:id:takuya_1st:20170224171539p:plain:w300

差分量による差異の計算

composie をしたときに、同じ部分は「黒色」に近づくので、より黒色に近いほどに差分がないことがわかる

identify -format "%[mean]" compsite-diff.png
## または 改行とファイル名を含めるなど
identify -format "%[mean], %f\n" compose-difference.png
  • 差分がない:0 に近くなる
  • 差分がある:0からどんどん離れる( 0(黒)〜65535(白)

目で見てわかりやすいやり方。

差を色でわかりやすくする

差分を計算するのとは異なりますが、画像を合成することで、見た目でわかりやすくするテクニックも見つけた。

事前処理で、差分を見る画像に色を付けておくと、少しわかりやすくなる

  • 元画像1:青系
  • 元画像2:赤系

事前処理

convert -type GrayScale +level-colors Red,White 1 .png 1_red.png
convert -type GrayScale +level-colors Blue,White 2.png 1_blu.png

合成処理

convert -compose Multiply -composite 1_red.png 1_blue.png a_b_diff.png

色の見方は次のとおりになる。黒系になれば両方に差分が有り、赤・青なら片方だけに差分がある。

白 × 白 = 白 
白 × 青 = 青
白 × 赤 = 赤
赤 × 青 = 黒

此の考え方だと、片方にしか無いものがより際立ってわかりやすくする事ができる。 事前処理で色数減らすのは頭いいなぁと思う。

サンプル

元画像を2色画像に加工します。

1_red.png : 元画像の赤色化

f:id:takuya_1st:20170224173255p:plain:w300

2_blu.png: 元画像の青色化

f:id:takuya_1st:20170224173300p:plain:w300

diff.png

  • 赤色:元画像1の部分にしか無い箇所
  • 青色:元画像2の部分にしかない箇所

と元画像の差分を視覚的に伝えることが出来ます。

f:id:takuya_1st:20170224173307p:plain:w300

さて何に使う?

  • 画像(動画)を圧縮したときの劣化率具合をみたり
  • 連写の違いをみたり
  • 動体検出の事前処理だったり
  • WEBページのレイアウト崩れだったり
  • WEBの広告枠がきちんと更新されるか
  • 巨大なExcelの細かい数字の違いを探したり
  • ダイアログが修正前後で同じか比較したり
  • イラレ原稿の変更箇所を伝える

画像を比較したら、結構あれこれできそうですよね。

スクリーンショットや、動画からの切り出しは便利ですよね。OpenCVでアコレいじくりまわすときでも複雑なことやら無くて済むので。役に立ちそう

追記

ImageMagick で画像を比較する - awm-Tech によると、SSIMを ffmpegで使うと簡単に劣化具合がわかるらしい

ffmpeg -i image1.jpg -i image2.gif -filter_complex ssim -an -f null -

magick にも限界があるのでffmpeg の利用も考えていきたい。

参考資料

compare コマンドで画像のズレを見つけろ!

ImageMagickにはcompareコマンドがある。

compare コマンドを使うと簡単に画像を比較することが出来る。

これはWebkit2png で取得した画像を使うとレイアウト崩れを見つけられるので嬉しいと思う

画像比較の例

compare -highlight-color red  1.png 2.png out.png

ひと目で差を見つけるのが難しいときも

f:id:takuya_1st:20170224165229p:plain:w150f:id:takuya_1st:20170224165218p:plain:w150

compare しておくとすぐわかる。

f:id:takuya_1st:20170224165224p:plain:w150

他にもいろいろな方法がある

  • compareを使う場合
  • compose を使う場合
  • convert composite を使う場合
  • compose mutipyを使う場合 色で見るのがわかりやすい
  • compose differenceを使う場合
  • compose AEを使う場合

参考資料

http://qiita.com/y_hokkey/items/417e108e212210b4e635#_reference-69fdebdf51dc682e5b67

/etc/passwd を編集しても反映しなかった。→ usermod を使う

/etc/passwd を手で編集した。

なぜだかわからない。反映しない。手作業で編集は駄目だと思ったけどshellや home dir や gid をマトメて編集できるから、もう直接手で触ればいいやとおもったけど反映しない。

home_dir を変更しても反映しない。。。再起動が必要だった。

シンタックスエラーはなかった

編集後にチェックして特にエラーがないことを確認

sudo pwck

専用コマンドを使うほうが無難だと思われる

ユーザーを操作するのは、専用コマンドを使ったほうが無難だと思う。

  • vipw
  • vipw -s
  • chsh
  • chfn
  • usermod
  • pwck

usermod であれこれ変更

usermod が便利なのでパターンとして覚えておくほうがいい

ホームディレクトリを変更

ホームディレクトリを別の場所に作り直す

usermod -d /var/home/takuya takuya

ホームディレクトリを移動

現在のホームディレクトリを指定の場所に移動させる。次からは指定の場所を使う。

usermod  -m -d /var/home/takuya takuya

シェルの変更

デフォルトシェルの変更。これはchsh でも出来る

usermod -s /bin/false takuya

ユーザーをロックする

ロックしてログインできなくする。

usermod -L takuya 

ユーザーをアンロックする

ロックしたユーザーを解除する

usermod -U takuya 

ユーザ名を変更する

ユーザ名を変更すると //home` も変更しないとログイン後にホームディレクトリが見つからないなどの問題が出てくるので注意

usermod -l takuya_1st takuya

設定の反映

ログイン中は設定が反映しないので、一旦ログアウトする必要がある。

/etc/{passwd,shadow}が間違ってないか

シンタックスエラーや記述ミスをチェックする

sudo pwck

/etc/passwd を編集する

sudo -e /etc/passwd はどうもうまく動かない*1なので vipw を使う

sudo vipw

参考資料

  • man usermod
       usermod  コマンドは、 コマンドライン上での指定によって、 システムアカウントファイルを修正する。 usermod コマン
       ドに指定できるオプションは次の通り。

       -c comment
              パスワードファイルのコメントフィールドに与える新しい値。 通常は chfn(1)  ユーティリティによって変更され
              る。

       -d home_dir
              新しいログインディレクトリ。 -m オプションを用いると、 現在のホームディレクトリの中身が新しいホームディ
              レクトリに移動される (後者が存在しない場合は新たに作成される)。

       -e expire_date
              そのユーザアカウントが使用不能になる日付。 日付は YYYY-MM-DD という書式で指定する。

       -f inactive_days
              パスワードの使用期限が切れてからアカウントが永久に使用不能になるまでの日数。 0 にすると、  パスワードの
              期限が切れると同時にこのアカウントは使用不能になる。   -1  にするとこの機能が無効になる。デフォルト値は
              -1。

       -g initial_group

              新たにそのユーザのログイン時初期グループとするグループ名または ID。  グループ名は既に存在していなければ
              ならない。 グループ番号は既存のグループを参照していなければならない。 デフォルトのグループ番号は 1。

       -G group,[...]
              ユーザが属する補助グループ (supplementary groups) のリスト。 グループはコンマで区切り、間に空白文字を入
              れてはならない。 指定できるグループには -g オプションと同様の制限がある。 現在そのユーザが、 新しいリス
              トにないグループのメンバーになっている場合は、 そのグループから削除される。

       -l login_name
              ユーザのログイン名を login から login_name に変更する。 他は何も変更しないので、 おそらく新しいログイン
              名に合わせて ホームディレクトリの名前を変更する必要があるだろう。

       -p passwd
              crypt(3) の返り値である暗号化パスワード。

       -s shell
              ユーザの新しいログインシェルの名前。 このフィールドを空白にした場合は、  システムがデフォルトのログイン
              シェルを選択する。

       -u uid ユーザの ID 番号。 この値は、-o オプションを用いる場合を除き、他と重複してはならない。 また非負値でなく
              てはならない。 0 から 999 までの値は、通常システムアカウント用に予約されている。 ホームディレクトリ以下
              の、 そのユーザ所有のすべてのファイルのユーザ ID は、 自動的に新しい値に変更される。 ホームディレクトリ
              以下にないファイルは手作業で変更しなければならない。

       -L     ユーザのパスワードをロックする。 これは暗号化されたパスワードの前に '!' を追加し、 実質的にパスワードを
              無効にする。 このオプションを -p や -U と同時に用いることはできない。

       -U     ユーザのパスワードをアンロックする。 これは暗号化されたパスワードの先頭の '!' を取り除く。 このオプショ
              ンを -p や -L と同時に用いることはできない。

*1: systemd になったあたりから、systemd 関係してる?

ネットワークのIPアドレスを一覧表示する(sort でIPアドレスをソート)

ローカルネットワークのIPを列挙する

nmap を使って、ネットワークに疎通できるIPアドレスがどれだけあるか見ておく

takuya@Desktop$ nmap -sP 192.168.2.0/28 | /usr/bin/grep -o '192.168.2.\d' 
192.168.2.1
192.168.2.2
192.168.2.3
192.168.2.9

うちのローカルネットワークだと1−9の数台しか使ってないのであまり違いが出ない

sort であれこれソートできる

もっとたくさんのIPアドレスが出てくる場合はソートしないといけない

IPアドレスは、バージョンの記述に似ているので、バージョン番号でソートする機能と同じように使える。

sort -V 

やってみた。

takuya@Desktop$ for i in {1..10}; do echo  192.168.$(( $RANDOM%254 )).$(( $RANDOM%254 )) ; done  | sort  -V
192.168.54.9
192.168.88.230
192.168.91.181
192.168.105.133
192.168.130.186
192.168.134.246
192.168.153.65
192.168.185.8
192.168.240.5
192.168.250.31

うん、きれいに数値順にソートされる。