それマグで!

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

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

Windowsにコマンドを流し込む(その他の方法

winexe というコマンド

Linux側から、Windowsにコマンド実行をさせるコマンドです。認証や実行はSambaと同じやり方でやってます。winexec 関数ではないです。

winexe コマンドでwindowsに仕事をさせる

winexe -U takuya //192.168.11.111 "cmd.exe "

winexec でWindowsにコマンドを流し込んだ結果

ipconfig

winexe のインストール

OSX なら brew で。

brew install winexe

winexe でつなぐための準備

さすがに、コマンドをいくらでも実行できるとセキュリティ上の問題があるのでWin7では機能が無効化されている。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System

にDWORDを作る

regedit

LocalAccountTokenFilterPolicy = 1

に設定すると、有効になる set1

ポリシーを設定していないとエラー

nt_error

このように、コマンドを実行させない。安全。

接続して使ってみる。

windowsにコマンドに入れ込む

パスワードを入力をして・・・

password

コマンドを実行する。

winexe -U takuya //192.168.11.111 "cmd.exe "

cmd.exeを実行すると対話型で行ける。

cmd

winexe -U takuya //192.168.11.111 "ipconfig.exe "

ipconfig

好きなだけコマンドを実行できます。

感想など

どう考えてもバックドアです。レジストリで作れる、バックドアです。

Win7では標準で無効化されているのでちょっと安心です。

レジストリの項目一つで、ここまで出来るとか、どう考えても危ないんですけど。。。この設定がAdministratorユーザーで最初から使えたらしいWindowsXPって本当に怖かったんだな。、、、

わたしは、Cygwin OpenSSH でいいです。。。

参考資料

winexe 配布元

http://sourceforge.net/projects/winexe/

Psexec

似たようなツール

PsExec

レジストリについて - Description of User Account Control and remote restrictions in Windows Vista

その他参考資料

  • LinuxからWindowsにコマンドを入力 | sound of rudeness
  • SUSE Linux から リモート Windows を制御できる winexe とPStools : 非番のエンジニア
  • Linux→Windowsリモートコマンド操作 - 色々日記(ざ・めも)

  • TimeMachineに容量制限を加える(netatalk)

    TimeMachineが容量を限界まで使う。

    TimeMachineは容量を限界まで使って初めて過去のバックアップ削除に手を付けるようです。

    しかもディスクをmountしてると、マウント元のHDDの容量をチェックしていて実際にマウントしたディスク容量をチェックできない。。。こまった。

    HDD食いつぶされたわ・・・

    容量制限を書ける

    そんな時のために容量制限を書くことが出来る。便利ですねぇ

        vol size limit = 200000

    出来上がった netatalk の設定

    タイムカプセルはあってもなくてもいいんだけど、安心感のために。

    寝てる間にタイムカプセルにバックアップが終わってるのが、精神衛生上に非常に素晴らしい。 家に帰って充電しておくだけですからね。

    ;
    ; Netatalk 3.x configuration file
    ;
    
    [Global]
        mac charset = MAC_JAPANESE
        hostname = atom-afp
    
    [Homes]
        basedir regex = /home
    
    [videos]
        path = /path/to/ts_video/
        time machine = no
    
    
    [My Time Machine Volume]
        path = /path/to/backup-images/time_capsule/
        time machine = yes
        vol size limit = 200000

    そうえいば、AFP 経由でファイルサーバを見ると

    アイコンがかっこいいい。液晶ディスプレイで表示されるのはnetatalk のマシン

    Sambaサーバーのアイコンがヒドイ・・・

    afp

    そういえば、最近Samba使ってないなぁ

    関連資料

    http://takuya-1st.hatenablog.jp/entry/2014/04/07/013519

    複数写真の一番簡単で最強に便利な共有方法 - 画像を pdf にしてアルバム化

    送る方も、受け取る方も一番楽な写真の受け渡し方法

    写真を受け渡す時に、色々とめんどくさい。Zipファイルにするのか。自己解凍形式にするのか、それとも、メールに複数添付するのか。

    パスワードを付けたかったり、イベント事にまとめたかったり、サムネイルを付けたかったり・・・・

    お悩みを一度に解決する方法があります。

    PDFにするのです。

    これを知った時は私も目から鱗が落ちる感じでした。そうかそうだよね。そうなんだよね。コロンブスの卵でした。

    これ にすることで

    • パスワードをかけられる
    • ファイル名に悩まない。
    • イベント毎に管理が楽
    • プレビューペインで見られる
    • フォルダ管理が楽
    • 添付も楽

    なんだ、これ。HTML化以上に素晴らしいじゃないか。

    作り方

    たったこれだけ!作り方も楽ちん

    convert *.jpg  my_album.pdf

    convert コマンドは imagemagick に付属のコマンドです。これでPDFを作成できます。

    出来上がったPDFはこんな感じ

    AdobeReader で簡単に見られる。

    album

    複数写真を一度に

    album

    OSX のプレビューでも

    サムネイル表示(左柱)

    album

    コンタクトシートで一覧もできる

    album

    すごく便利だし、まとめているので紛失しない!

    ちゃんとしたアルバムです。れっきとしたアルバムです。

    注釈やメタデータもちゃんとファイルに書き込めます。

    添付処理も楽ちん

    メールやiMessageで添付するときやSkypeで送信するときも、PDFファイル一つにまとまっているので楽ちん!

    細かいオプション

    このコマンドだけだと、画質やファイルサイズの問題があるので・・・

    convert *.jpg  my_album.pdf

    DPIで解像度指定や、画像圧縮、ページサイズ、リサイズを指定するともっと扱いやすい

    convert *.jpg  -density 100 -quality 100 -page 600x600 -resize 600x600 my_album.pdf

    density : DPI解像度。デフォルト値は72、印刷用なら300以上かな

    quality : JPEGの再圧縮率 0 が最高圧縮 100 が無圧縮

    page : 1ページのサイズ(ピクセル

    resize : 貼り付け画像のサイズ(ピクセル)

    更に開封用のパスワードを設定など

    アルバムをそのまま渡すには、PDFにパスワードを設定するといい。画像ファイルをZIPで送るよりも、PDFにパスワードを追加したほうが安全だし相手も嬉しい。

     pdftk album.pdf output out.pdf \
       encrypt_128bit\
       allow Printing CopyContents \
       owner_pw my_password \
       user_pw   Passowrd123456
    

    user_pw で開くときのパスワードを設定。このばあい「Passowrd123456」を指定。

    allow と owner_pwとでPDFで閲覧印刷、編集などのパーミッションつけて改変を防ぐ

    写真を送るときにzip ファイルでパスワードを付けるよりずっと楽ですね。

    まとめ

    convet コマンドとpdftk の組合せで、手軽にアルバムを作ることが出来る。

    この他にも、PDFに注釈や製作者、またPDFなので、ページを追加して文章も貼り付けることが出来る。

    メールであれこれ送るときに非常に便利に使えそうですね。

    HTML文書中にPDF埋め込んだら業務上の文章が殆ど事足りそう。Excel方眼紙職人さんにドヤ顔できそう・・・

    参考資料

    http://j.mp/1jPDd1J

    元ネタは、PDF Hacksの本で教わりました。写真の配布に使うアイディアが一番心にグッときました。

    更新

    • 2020-04-16 Google検索でマッチしないので、表現を変更

    convert コマンドのOpenMP高負荷らしい問題

    ImageMagickopenMP利用に不正確な部分があって、高負荷らしい

    参考資料

    OMP_NUM_THREADS=1

    さっそく ビルド見てみよう

    takuya@rena:/usr/local/Cellar/imagemagick/6.8.9-1$ convert --version
    Version: ImageMagick 6.8.9-1 Q32 x86_64 2014-08-02 http://www.imagemagick.org
    Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
    Features: DPC Modules
    Delegates: bzlib cairo fftw fontconfig freetype jng jp2 jpeg lcms lqr ltdl lzma openexr png rsvg tiff webp x xml zlib
    takuya@rena:/usr/local/Cellar/imagemagick/6.8.9-1$ cat INSTALL_RECEIPT.json | jq .
    {
      "used_options": [
        "--with-fontconfig",
        "--with-ghostscript",
        "--with-jp2",
        "--with-liblqr",
        "--with-librsvg",
        "--with-libtiff",
        "--with-libwmf",
        "--with-little-cms",
        "--with-little-cms2",
        "--with-openexr",
        "--with-perl",
        "--with-quantum-depth-16",
        "--with-quantum-depth-32",
        "--with-quantum-depth-8",
        "--with-x11",
        "--with-webp"
      ],
      "unused_options": [
        "--without-magick-plus-plus",
        "--without-jpeg",
        "--without-libpng",
        "--without-freetype"
      ],
      "built_as_bottle": false,
      "poured_from_bottle": false,
      "tapped_from": "Homebrew/homebrew",
      "time": 1406912136,
      "HEAD": "db71783ad26f0277fa1d565bed14302051b5f011",
      "stdlib": "libcxx",
      "compiler": "clang"
    }
    

    なんだ、HomeBrew経由のImageMagickopenMP使ってない。そりゃOSXだし当たり前か。

    Debianの convert はというと

    takuya@atom:~$ convert --version
    Version: ImageMagick 6.7.7-10 2013-09-01 Q16 http://www.imagemagick.org
    Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
    Features: OpenMP
    

    DebianのデフォルトパッケージはOpenMPが有効でビルドされてました。

    そのままで実行

    実験したマシンはこちらも Corei7 (Lynnfield) TOPで見てたらCPUの負荷率は400% くらい

    takuya@atom:~$ time for i in {1..10}; do convert image2.jpg -deskew 40% out.jpg  ;done
    
    real    0m25.751s
    user    2m0.700s
    sys 0m1.204s

    TOPで見てたらCPUの負荷率は100% くらい

    takuya@atom:~$ export OMP_NUM_THREADS=1
    takuya@atom:~$ time for i in {1..10}; do convert image2.jpg -deskew 40% out.jpg  ;done
    
    real    1m16.499s
    user    1m15.329s
    sys 0m0.928s

    目に見えて変わるものでもないので気にしないことにする。

    高負荷は、たしかにそうなんだけど、 real の秒数が何度やっても OpenMP使ったほうが圧倒的なんだけどな。。。高負荷はたしかに問題あるとは思うけど。常に処理してるマシンでもない限り気にしなくていいってことだな。

    imageMagickのconvert で標準入出力 stdout/stdin を使う

    convert 処理をraspberryPiですると遅い

    RaspberryPiにConvetコマンドを処理させるとめちゃくちゃ遅い。斜め補正をraspberrypi の別のプログラムから呼び出したらすごく遅かった。

    convert naname.jpg -deskew 40% hosei.jpg

    これを、Corei7のDebianなら10-20 秒程度だが、RPi だと240秒(4分)近かった

    convert コマンドをSTDIN/STDOUTでSSH経由で活用する

    ssh 経由で、標準出力と標準入力を使って処理を別サーバーに任せる。

    cat src.jpg | ssh takuya@192.168.100.2 " convert - -deskew 40% -  " > dst.jpg

    CPUリソースは限られてるけれど、ネットワークリソースなら余っているので。そちらに処理を任せる。

    convert コマンドで stdio

    command | convert - -option arg -  | command

    と 「- 」(ハイフン)を使ういつもの標準出入力を使う方法で、全く問題なく処理ができる。

    余ってるリソースを積極活用はいい感じの分散処理の基本だもんね。

    ImageMagick の convert で傾き補正して斜めスキャン修正する

    スキャナの性能が微妙で斜めにスキャンされる

    ADFでスキャンすると紙送りが下手なスキャナだと、歪んでスキャンされてしまうことがある。

    微妙に斜めになっている画像の向きの傾きを修正した居。

    歪んでしまっても諦めない

    convert src.jpg -deskew 40% out.jpg

    何度もスキャンをリトライしてやり直すのもいいけれど、ちょっとくらいなら補正が効きます。

    ImageMagickはすごいね!!convert コマンド便利

    補正したサンプル

    左:補正前、右:補正後

    素晴らしいです。傾きを補正できると、スキャナーの活用が積極的に出来そうです。

    FacebookのメッセンジャーはiMessage.app(jabber)から使える。

    LINEに疲れて果ててるTakuyaです。こんばんは

    LINEラインラインってうっさいハゲと言ったいわけですが。LINEの問題とか、以下にしてLINE依存をやめさせるかとか不毛な議論をしてる間がアレば、別のメッセンジャーを使えばいいじゃないと思うわけです。1アカウントで使えるという区別すらLINEが無い頃は存在しない区別だった。各種端末でいちいち、アカウント取得し直さなくちゃいけない、LINEっって早く消えてほしい。SMSとメッセージと、マルチログインが対応しててグループチャット対応で、ほとんどのユーザーデバイスに標準搭載されているものは、以下のとおり

    PC(win/OSX)と、タブレットスマートフォンを1アカウントで使える

    このへんがもっと普及してほしいな。

    Facebookメッセンジャーはなかなかいい。

    Facebookメッセンジャーは、実は、Jabberで使えるので、iMessge.app に設定すれば、ちゃんとつかえるんだお。

    facebook の解説

    https://www.facebook.com/sitetour/chat.php に解説されてる通り。

    Facebookメッセンジャーは専用アプリを使わずとも、Jabber対応なので、Google Talk系と併存できて便利なんですね。 スクリーンショット 2014-06-12 19.52.06

    実際に設定した例が以下

    スクリーンショット 2014-08-01 20.10.54

    jabber対応なら便利じゃん。

    Facebookを見なおした。

    LINEは、色々と制限が増えてきたりするので、端末買い換えるたびに使われなくなるんじゃないのかな。

    SMS非対応ってのが痛いよね。

    LINE はなぜここまで流行ったのか?

    スタンプ?背景?いいえ、iPhone/Androidメッセンジャーで手軽だったからです。

    手軽に使わせるために、サーバーにアドレス帳電話番号を強制アップロード&強制レコメンドというちょっと強引な手法を使ってたわけですし。

    LINE サヨナラしたいからFacebookも選択肢

    10年前の切れた友人がレコメされても、どう考えてもそれ、本人じゃないし、私のGmailの古いアドレス帳をいつ持っていった。。。

    LINEは便利なんだけど、メインで使うには色々とめんどくさいので廃れるのをじっと待ちます。 あと3年ってところでしょうか。

    PHPの文字列結合で抜けが致命傷になる

    セミコロンを忘れたら大変なことになった

    <?php
    $str = "xxx";
    $str .= "aa" .
    $str .= "bb";
    echo $str."\n";
    

    実行結果

    xxxbbaaxxxbb

    これはツライ。一瞬何がなんだかわからなかった。

    文字列の結合は再帰的に動作するので

    $str = "xxx";
    $str .= "aa" . $str .= "bb";

    と解釈されて

    xxx
    $str .= "aaa". "xxx"."bb";//この時点で $str = "xxxbbb"
    "xxx"."bb" . "aaa". "xxx"."bb" 

    焦る。。。。一個抜けただけで想像もつかない文字列になった。

    フォームのPaste禁止の禁止

    email アドレスの確認でペーストすると怒られる。

    メールアドレス を貼り付けようと思ったら・・・・

    スクリーンショット 2014-07-31 20.38.36

    どうせ、フォーム自動入力でレコメンドされるんだろうし、2回入力する意味ってあるのかな。

    ペーストを禁止する

    <element onPaste="alert('ペースト禁止');return false;" .. > ... </element>
    

    input に書くと思ってたら、ノードはなんでもいいようだ

    <td class="form_tdl_g" onpaste=" alert('確認のため、再入力をお願いします。');return false"></td>

    html はどこでも編集ができるのでペーストが出来るところは、input 要素とは限らないので要素は人のようだ。

    ペーストの禁止を禁止する

    Array.apply(null, document.querySelectorAll("*[onpaste]") ).forEach(function(e){e.onpaste="return true;"})
    

    ブックマークレット

    ブックマークレットにしていつでも呼べるようにした。

    javascript:Array.apply(null%2C%20document.querySelectorAll(%22*%5Bonpaste%5D%22)%20).forEach(function(e)%7Be.onpaste%3D%22return%20true%3B%22%7D)``

    chrome拡張

    chrome の content の js として登録したらいい←あとで書く

    JavaでWEBページ取得。プロキシ経由

    JavaでWEBページ取得をしたら、プロキシが必要なのを忘れてた

    Java の URL を使ってProxy経由でページ取得

    通常のURL.open

    URL url = new URL(page_url);
    URLConnection conn = url.openConnection();
    

    Proxy 経由の URL.open

    //
    URL url = new URL(page_url);
    //学校のプロキシを使う設定。
    String proxy_url   = "prxsrv.example.jp";
    String proxy_port  = "8080"; 
    //Proxyクラス作成
    Proxy proxy = new Proxy(
                               Proxy.Type.HTTP, 
                               new InetSocketAddress(proxy_url, Integer.parseInt( proxy_port )  )
                   );
    //Proxyを設定
    URLConnection conn = url.openConnection(proxy);
    

    意外と簡単にProxyサーバーを使うことが出来た。

    JavaでWEBページ取得。file_get_contents的なこと

    Javawget をやったらどうなるのか考えたら、めんどくさそうだった。

    どこまで長文になるのか試しにやってみた

    java で ネットワークのファイルを取得

    WEB ページを取得して title 要素抜き出す

    import java.net.URL;
    import java.net.URLConnection;
    import java.net.Proxy;
    import java.net.InetSocketAddress;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    class Title{
      public static void main(String[] argv) throws Exception {
          String title  = Title.getTitle(argv[0]);
          System.out.println(title);    
        }
      public static String getTitle(String page_url) throws Exception {
        //アクセスしたいページpage_url
        URL url = new URL(page_url);
        URLConnection conn = url.openConnection();
    
        String charset = Arrays.asList(conn.getContentType().split(";") ).get(1);
        String encoding = Arrays.asList(charset.split("=") ).get(1);
    
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), encoding )); 
        StringBuffer response = new StringBuffer();
        String line;
        while ((line= in.readLine()) != null) 
                response.append(line+"\n");
        in.close();
    
        Pattern title_pattern1 = Pattern.compile("<title>([^<]+)</title>",Pattern.CASE_INSENSITIVE);
        Matcher matcher1 = title_pattern1.matcher(response.toString());
        if(matcher1.find() ) {
          return matcher1.group(1);
        }
        return null;
      }
    
    }
    

    使い方

    javac Title.java
    java Title https://mixi.jp
    java Title http://www.yahoo.co.jp/
    

    解説

    色々と面倒なことがありそうなので、とりあえず、あとためにメモっておこう。

    ネットワークをOpenする。

        URL url = new URL(page_url);
        URLConnection conn = url.openConnection();
    

    InputStreamとして読み込む。

    InputStream は InputStreamReaderを使って、Reader(いつものファイル)と同じように扱って、 BufferedReader で、読み込みをバッファリングしている。

    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), encoding )); 
    StringBuffer response = new StringBuffer();
    String inputLine;
    while ((inputLine = in.readLine()) != null) 
        response.append(inputLine+"\n");
     
    in.close();
    

    文字コードを変換するための情報を取得

    Content-Typeの文字コードを取得して、InputStreamReaderを開くときに文字コード指定に使う

        String charset = Arrays.asList(conn.getContentType().split(";") ).get(1);
        String encoding = Arrays.asList(charset.split("=") ).get(1);
    

    Array.asList で、Listとして配列を扱う。

    StringをSplitすると、String[] (String の配列)が戻されるので、それは扱いにくいのでCollection 対応させる・。

    charset.split("=") // => String[]
    Arrays.asList(charset.split("=") ) //=> List<String>
    Arrays.asList(charset.split("=") ).get(1); //=> String

    StringBuffer response

    文字列結合を連続して行うときの定番

    StringBuffer response = new StringBuffer();
    response.append(line);

    StringBufferでも、StringBuilderでも構わない。

    正規表現で、マッチして、後方参照

    HTMLのTitleタグ中から、正規表現でテキストノードを正規表現で取得する。

        Pattern title_pattern1 = Pattern.compile("<title>([^<]+)</title>",Pattern.CASE_INSENSITIVE);
        Matcher matcher1 = title_pattern1.matcher(response.toString());
        if(matcher1.find() ) {
          return matcher1.group(1);
        }
    

    大文字小文字を無視した正規表現パターンを作る。

    Pattern title_pattern1 = Pattern.compile("<title>([^<]+)</title>",Pattern.CASE_INSENSITIVE);

    マッチさせる

        Matcher matcher1 = title_pattern1.matcher(response.toString());

    正規表現にマッチした箇所があったか?あれば、中身を取得

        if(matcher1.find() ) {
          return matcher1.group(1);
        }

    引数が取れる。

      public static void main(String[] argv) throws Exception {
          String title  = Title.getTitle(argv[0]);
          System.out.println(title);    
        }

    引数の argv の配列には、コマンドの引数が入るが、argv[0]が自分自身のファイル名になることはない。

    感想

    いーかげんJavaの顔も見たくないと思った。もっと簡単なやり方あるんですかね? 仮にあったとしても、一番最初に習う書き方で、教科書的に書いた結果がこれでは・・・

    でも、いい感じに抽象化されていて、 https/http も問題なく URLで扱えるのとかいいなと思った。

    URL classで抽象化してるわりに、このへんはストリームが見えてて、意図が良くわかなんない。

    getInputStream()は気持ち悪い。HTTPのプロトコル的にkeep-alive を指定しない限りCloseだし。中身とったら終わりだから。ストリームは見えなくていいような。

    URL.Connection やinputstreamがあるのは、Javaの基本APIの設計思想に理由があるのかな。JavaはOSのシステムコールに近いものを意識してるから仕方ないよね・・・

    バッファリングとか必要なんだろうかと思いながらも、教科書通りってことでいつも書くんだけど。やっぱよくわからん。

    String とか ObjectJavaのなかでも一番わかりくく使いにくい。

    StringBuilderとか実際は、String += String と書いてたら、javacが最適化して内部的に使ってたから僕らは気にしなくてよかったような。

    自分自身のファイル名の取得はどうすんだろうな。Runtimeあたりかな。

    StringBufferとStringBuilderの違い

    http://www.javainthebox.net/laboratory/J2SE1.5/TinyTips/StringBuilder/StringBuilder.html

    指定行削除するコマンド(sed

    指定した行を削除したい。

    ファイルを開くのすら面倒じゃないですか?

    sed でファイルを編集

    sed -i -e '10,10d' /path/to/file

    10 行目を消す。

    sed で簡単にファイルを編集

    sed -i -e '15d'  /Users/takuya/.ssh/known_hosts

    sed は stream edior の ed 拡張版です。ed コマンドは、Vim使ってる人ならだれでも知ってるアレです。つまり、sed のコマンドは vim のコマンドです。わかりやすい!っていうか、vi コマンド モードが edの拡張版で、 vim が vi の拡張版で、ed のパイプライン対応が sed だからなんですが。つまり、ed の祖先が同じだから、sedvim は 従兄弟?

    ファイルを編集して上書きする -i オプション

    sed -i  ... ファイル

    この-i を使うと、ファイルを編集して上書きする。

    コマンドを指定する。 -e

    sed のコマンドを -e で指定する。

    sed -e '1,$d' /etc/hosts

    2行目から末行まで全部消す。

    1行目だけを残す。

    sed -e '2,$d' /etc/hosts

    簡単な使い方。

    sedに深入りすると大変なので、、、ドール沼より、怖いvi /sed 沼だと思うので、深入りせずに、ちょっとだけ。

    vim と違ってるのは行省略かな。sedは行番号の省略時の動作が異なる。vim が行を指定しない時にカレント行になるのたいし、sedでは標準入力で入ってきた各行に順番に適用される。ってことが違いかな。

    1行目を消す

    sed -e '1d' /etc/hosts

    最終行を消す

    sed -e '$d' /etc/hosts

    7-9行目を消す

    sed -e '7,9d' /etc/hosts

    行番号をつける

    sed -e '=' /etc/hosts

    置換する

    sed -e 's/foo/bar/g'  /etc/hosts

    複数ファイルをまとめて扱う

    sed -e 's/foo/bar/g' File0 File1 File2...

    例えばこんな時:

    ssh でのauthorized_keys を書き換えるとき。

    サーバーのIPアドレスが違うときにHostKeyチェックで落ちる。SSHで port forwarding やトンネル作ってる時によく起きる。面倒じゃないですか?

    takuya@rena:~/Desktop$ ssh root@192.168.2xx.3xx reboot
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that a host key has just been changed.
    The fingerprint for the RSA key sent by the remote host is
    95:56:53:34:10:88:cf:xx:xx:xx:xx:xx:xx:xx:xx:xx.
    Please contact your system administrator.
    Add correct host key in /Users/takuya/.ssh/known_hosts to get rid of this message.
    Offending RSA key in /Users/takuya/.ssh/known_hosts:15 # <------------ここ消せばいい
    RSA host key for 192.168.2xx.3xx has changed and you have requested strict checking.
    Host key verification failed.
    

    Strict host Key Check をオフにしろと言われそうですが、それはしない。

    該当行がわかってるので、ファイルを開いて探すのも面倒じゃないですか。

    2018/07/16

    記述を修正

    参考資料

    http://ja.wikipedia.org/wiki/Vi

    http://d.hatena.ne.jp/eel3/20110625/1308934448

    http://www.not-enough.org/abe/manual/command/vi.html

    rubyでinit.d スクリプトを作った。

    RaspberryPi 気に入って使ってます。Debianを入れてます。raspbian ですね。

    RaspberryPiがupstart未導入だったのでruby でinitスクリプト作った

    daemonsがお手軽

    gem install daemons
    

    Process.daemonizeがある昨今においてdaemonsパッケージは不要かと思ってたけれど、まだまだ使える。

    start/stop/resutart/run をすぐに作れる

    daemonsパッケージ使うと、initスクリプトに必要なコマンド引数をすぐに作ってくれる。

    Daemons.run_proc に Procを渡すだけ

    require "daemons"
    
    Daemons.run_proc("my_first_proc_daemon", options ){
      begin 
        server = Thread.new{   :job_server }
        woker = Thread.new {  :job_worker }
        server.start
        server.join
      rescue 
        #retry
      end
    }
    

    起動終了

    ./my_job_queue start
    ./my_job_queue stop
    ./my_job_queue status
    ./my_job_queue run # foreground に stay on topする
    

    RaspberryPi の init.d daemon にする

    :dir_mode => :system を渡して、 /var/run に pidファイルを作成するようにする。

    あとは、このファイルを /etc/init.d にコピーして、適当なRunlevelを貼り付ければOK

    適当なランレベル

    runlevel を貼るには、 /etc/init.d においたスクリプトを /etc/rc{0-5}.d/にエイリアスすればいい。数値は起動順序。

    面倒なときは、rcconf でパパっと。

    出来上がったinit.dスクリプト

    #!/usr/bin/env ruby
    ### BEGIN INIT INFO
    # Provides:          my_server
    # Required-Start:    $all
    # Required-Stop:     $all
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: my_server
    # Description:       my_server
    ### END INIT INFO
    
    require 'daemons'
    
    options ={
      :dir_mode => :system, ##/var/runに
      :backtrace => true,
      :monitor =>true,
      :log_dir => "/var/log/my_server",
      :log_output => true,
      
    }
    
    Daemons.run_proc("smtp_proxy_server", options ){
          server = Thread.new{  loop {sleep 1;print :awake;}  }
          server.pass
          server.join
    }
    

    プロセス監視する:monitor

    また、:monitor=>trueにすると、プロセスがErrorで死んだ時に再起動を自動で行ってくれて更に便利。

    options ={
      :monitor=>true,  
      ##以下略
    }

    monitorも便利です。

    monitorが無事起動すると、プロセスがひとつ増える。

    takuya@raspberrypi:~$ ps auxf | grep smtp
    root      2655  0.0  1.8  17684  9052 ?        Sl   04:51   0:06 smtp_proxy_server_monitor
    root      2662  0.0  1.3  13880  6760 ?        Sl   04:51   0:04 smtp_proxy_server

    smtp forwarder を ruby で作って起動し監視しています。

    INIT INFO については

    INITスクリプトは LSB (Linux Standard base ) で「こう書け」が指定されているのでそん通りに。

    ### BEGIN INIT INFO
    # Provides:          my_server
    # Required-Start:    $all
    # Required-Stop:     $all
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: my_server
    # Description:       my_server
    ### END INIT INFO
    

    大事なのは Required-Start で、ここを$all以外 にすると、ネットワークやファイルシステムが起動時点で起動するとか色々決められる。いまは $all なので全部の起動処理後にスクリプトをDaemonizeしてる。

    https://wiki.debian.org/LSBInitScripts

    upstart があれば。。。

    upstart がアレばもっと楽に書けるんだけど、自分で起動終了を管理したいこともあるってことと、 raspberryPiのDebianUpStart入ってないからです。 apt-getでインストール出来るんだけど、入れたら何か突然誤作動したら怖いので。

    参考資料

    http://rubydoc.info/gems/daemons/1.1.9/frames

    Rubyでメール送信のSMTPにGmailを使う。

    メールって「通知」を出すのに非常に手軽で便利ですよね。

    ruby でメール送信するときにGmailを使う

    starttls_auto と、 authentication, あと、パスワードを入力する。

    require 'mail'
    
    options = { 
      :address              => "smtp.gmail.com",
      :port                 => 587,
      :user_name            => 'takuyaXXXXXX@gmail.com',
      :password             => 'password',
      :authentication       => 'plain',
      :enable_starttls_auto => true  
    }
    
    Mail.defaults do
      delivery_method :smtp, options
    end
    
    mail = Mail.new do
      from     'takuyaXXXXXX@gmail.com'
      to       'takuyaxxxxxxxxx@m.evernote.com'
      subject  "EvernoteにPDFファイル送信   "
      body      "◯◯のPDF"
      add_file :filename => out_path, :content => File.read(pdf_path)
    end
    

    Rubyで添付ファイル付きメールの送信

    メールで添付ファイルを送りたいとき。

      add_file :filename => out_path, :content => File.read(my_file_path)

    ruby のmail を使ったらこんな感じ。

    #!/usr/bin/env ruby
    #coding:utf-8
    
    exit unless ARGV.size == 1
    my_file_path = ARGV.shift
    
    require 'mail'
    
    options = { 
      :address  => "localhost",
      :port   => 25,
      :authentication => 'plain',
      :enable_starttls_auto => true  
    }
    
    
    Mail.defaults do
      delivery_method :smtp, options
    end
    
    mail = Mail.new do
      from     'form-address@localhost'
      to       'user@localhost'
      subject  "mail test"
      body      "this is test mail "
      ## 添付ファイル処理
      add_file :filename => out_path, :content => File.read(my_file_path)
    end
    
    mail.deliver!
    

    添付ファイルをつけるには、オプションを追加するだけなので簡単です。