それマグで!

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

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

Rubyでシェルコマンド実行後のステータスコードを取得する

Rubyで外部コマンドを実行して、コマンドの実行結果をまって次のコマンドを実行したい時とか

コマンドの終了は $?.exitstatus で出力する

?> `ls /` 
=> "bin\nboot\ncdrom\ndev\netc\nhome\n"
>> $?
=> #<Process::Status: pid=8707,exited(0)>
>> $?.exitstatus
=> 0
>> 

存在しないコマンドの場合

>> `gheohgeo` 
(irb):18: command not found: gheohgeo
=> ""
>> $?
=> #<Process::Status: pid=8728,exited(127)>
>> $?.exitstatus
=> 127

コマンド終了ステータスでSSHの生死を確認してみるとか。

台数が多いとさすがに大変。Zabbixとか監視ツール入れたら楽なんだけど、そもそも、その環境を作る過程では手動で確認しなくちゃいけない。

SSHコマンドが実行できるかで、生死確認をまとめて行う

puts (1..100).map{|i|  "192.168.100.#{i}"}.map{|ip| `ssh #{ip} "pwd"`;$?.exitstatus == 0 }.size == 100

SSHでコマンドが実行できたらTrue。全台起動したらTrueです

コマンド実行はBashよりruby移行がオススメ


shell ライブラリというツールがある。覚えにくい時はこれを使う

require 'shell'
sh = Shell.new
sh.ls "/"

sh.transact{ 

cat "/etc/resolv.conf"
mkdir "/tmp/test-1"
cat"/etc/resov.conf"  > STDOUT

}

Shell使うと、rubyと通常シェルの区別が限りなく見えなくなってくる。

bashの代わりにrubyはいい選択肢だと思うよ。

2012/02/17追記

なんか書いてから3ヶ月後にブクマされまくってる。

transactは正しくはこう

sh.transact{system("ls", "-l") | head > STDOUT}


最新版のRubyだと動かなかった。僕が書いたのサンプルは間違ってる。

sh.transact{ 
cat"/etc/resov.conf"  > STDOUT
}

のようなことは、()省略の規制と順番の関係できないみたい。もったいないよねぇ。1.9の変更だとこの方向の進化が完全に打ち消されちゃう・・ね。1.9好きになれないなぁ。

Rubyでメールを送るTMailのよくある使い方。(Return-path・添付ファイル・gmail/TLS)

Rubyでメールを送るにはTMialを使う。

Rubyでメールを送るTMailでいろいろやってみた。


TMmailはメールの統合ライブラリ。なのでサポートしている規模が大きい。

  • メールパーサー
  • MBoxパーサー
  • メール作成
  • 添付ファイル処理
  • エラーメール処理

などなど

各種機能がある。ただし、それぞれ実装されたタイミングなのか、APIに若干の設計思想の違いがあり、ちょっと戸惑うことが多い。

本家をみながら試した

TMail ユーザーマニュアル

単純送信

まずは単純なテキスト送信から
これを参考に→Ruby/TMail - 俺の基地

require 'net/smtp'
require 'tmail'
require 'base64'

mail = TMail::Mail.new

mail.to = 'takuya@example.jp'
mail.from = 'takuya@from.example.jp'
mail.subject = 'Test Mail Title '
mail.date = Time.now
mail.mime_version = '1.0'
mail.body = 'This is test mail.'
mail.set_content_type 'text', 'plain', {'charset'=>'iso-2022-jp'}

#送信
Net::SMTP.start("localhost","25","local","username","password","plain") do |smtp|
  smtp.sendmail( mail.encoded, mail.from, mail.to)
end

username, password は、localhostの認証無しであればnil,nilでいい

これでOK.とりあえずここまでで、テキストメールは送れる。

添付ファイルだけを送信

つぎは添付ファイルだけを送ってみる。
このメールでは本文の代わりに添付ファイルだけをアタッチする。

このブログのを参考に→TMailで添付ファイル付きメールの送信 - みずぴー日記

require "rubygems"
require 'tmail'
require 'base64'

mail = TMail::Mail.new

##ヘッダ
mail.to   = 'takuya@to.example.com'
mail.from = 'takuya@from.example.com'
mail.subject = 'Test mail Title'
mail.date = Time.now
mail.mime_version = '1.0'

##ファイルを添付
attach = TMail::Mail.new
attach.body = Base64.encode64(open('/tmp/test-1.jpg').read)
attach.set_content_type 'image','jpg','name'=>file
attach.set_content_disposition 'attachment','filename'=>file
attach.transfer_encoding = 'base64'
mail.parts.push attach

#puts mail.encoded
#送信
Net::SMTP.start("localhost","25","local","","","plain") do |smtp|
  smtp.sendmail( mail.encoded, mail.from, mail.to)
end


これで添付ファイルは送れる。

重要?!添付ファイルと本文を送る

なぜかTmailは本文をPartsに入れないとダメらしいので(というか改行の取り扱い?)本文もPartsに入れるとうまくいく。

Bodyにテキストをいれて添付ファイルをつくけたらbody消えた。メソッド呼び順かなと思ったら。エンコードされたデータを見てなるほどね。

添付ファイル付きのメールというのは、内部ではメールに本文の内容と、添付ファイルの内容が2つ添付されている状態と言える。

Ruby/TMail - 俺の基地

添付ファイルをつけて本文をつける。
require 'net/smtp'
require 'tmail'
require 'base64'

#入れもの
mail.to = 'takuya@example.jp'
mail.from = 'takuya@from.example.jp'
mail.subject = 'Test Mail Title '
mail.date = Time.now
mail.mime_version = '1.0'
mail.body = 'This is test mail.'
mail.set_content_type 'text', 'plain', {'charset'=>'iso-2022-jp'}
mail.set_content_type 'multipart', 'mixed', {"boundary" => "fooooooooooooooooooobarr"}

#本文
mail_body = TMail::Mail.new
mail_body.set_content_type 'text', 'plain', {'charset'=>'iso-2022-jp'}
mail_body.body = 'これはテストですテスト'
mail.parts.push(@mail_body) #本文も添付

# 添付ファイル
attach = TMail::Mail.new
attach.body = Base64.encode64 File.open('foo.jpg', "rb").read
attach.set_content_type 'image','jpg','name'=>'foo.jpg'
attach.set_content_disposition 'attachment','filename'=>'foo.jpg'
attach.transfer_encoding = 'base64'

# 添付
mail.parts.push(attach)

#送信
Net::SMTP.start("localhost", 25 ) do |smtp|
  smtp.sendmail(mail.encoded, mail.from, mail.to)
end

これで添付ファイルと本文を送ることができた。mail.parts.push(@mail_body) #本文も添付がポイントっぽい。

GmailなどのSMTPSサーバーで送りたい

GmailSMTPでなくSSLレイヤ上で通信をするのでモジュールが違う

require 'tlsmail'
  Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
    Net::SMTP.start("smtp.gmail.com", 587, "local", @username, @password, "plain" ){|smtp|
        smtp.sendmail(
        @mail.encoded,
        @mail.from,
        @mail.to )
    }

に変更になる。

Return-PATHヘッダをつける。

大量送信やバッチ送信の場合にはエラーメールを一括で受け付けるためのヘッダを付記する。
それをReturn-Pathという。ReturnPathのためにFromを偽装しなくていいのがうれしい。

ReturnPathのTmailでの使い方。

mail = TMail::Mail.new
mail["Return-Path"] = “return@example.biz"
mail.to = "takuya@example.biz"
mail.from "from@example.biz"
mail.subject= "testmail for returnpath "
mail.body="test for test of return path"
mail.encoded

出力結果

Return-Path: <error-handler@example.jp>
From: from-autosender-@example.jp
To: takuya@example.jp
Subject: test for adding Return path


ReturnPathを作ると、メールのFromでなくReturnPathに指定されたアドレスにメールが届く。

総括です。

TMailはよくできている。不足機能は全くない。ただし、E-Mailの知識は必要。
アタリマエのことだけれど、それを隠すべきか隠さざるべきは、別の問題。Tmailは良く出来てる。

不要な機能は隠し、必要な機能でAPIや呼び出し順を好きな方にした、Wrapperクラスを作ったりするのが便利そう。

Macで ddしたCD/DVDイメージをマウントする。

MacでDDしたイメージをマウントする。

ddでイメージ取り出したあとに、ISOファイルをマウントするには

sudo hdiutil mount web_db.iso

ディスクイメージを使ってるとこれが便利。
まぁいろいろやり方はあるけど、仮想ディスクのマウント程度ならターミナルでやってまえばいいよね。

マウントできた!

takuya@air:~$ mount 
/dev/disk0s2 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
/dev/disk0s4 on /Volumes/BOOTCAMP (ntfs, local, read-only, noowners)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
/dev/disk1 on /Volumes/webdb_sp (udf, local, nodev, nosuid, read-only, noowners)
takuya@air:~$ 

loopとか指定しなくていいから、コマンド覚えやすい。便利!

 いますぐコマンドプロンプトを捨てて、Cygwinを使うべき10+の理由

Mac大流行なのでCygwinに需要ないかもしれないけど。一年間のCygwin体験をまとめてみた。今年1年で一番使ったツールで感謝してる。


CygwinはWindows環境にそのままLinuxCUIツールを導入できる。もう「コマンドプロンプト」に拘る必要は薄くなりました。

僕は今年1年の一番の収穫はCygwinを使ったこと。

Cygwinを使うことでターミナルを使いこなせるようになった。そしてMacに移行してもターミナルさえあるから困らないと思えるようになりました。

コマンドプロンプトを捨てるべき理由

SSHコマンドでリモートサーバにアクセスしても文字化けする。
・色・フォントがダサくて使い物にならない。
・コマンドが少ない。grep したい。findしたい

cmd.exeをすててMinttyを使おう。

Cygwinを使うと、minttyというPuttyベースの素晴らしい。ターミナルがついてきます。

CygwinはWindowsにLinuxのコマンド群を移植したものです。

Cygwin+Minttyにすると

  1. ターミナルが綺麗。
  2. 文字化け知らず
  3. Linuxのコマンドはほぼ使える。
  4. SSHが便利
  5. Rsyncが便利
  6. レジストリ読むのが便利。
  7. 簡単にコマンドが入る。
  8. javacなくても大丈夫。
  9. Vimとか便利になる。
  10. ddコマンドあるよ。
  11. SambaのNASも簡単よ。
  12. パス名は適当でいい
  13. iso作れるよ。
  14. passwdも変更できる
  15. 任意のマウントできるよ。
  16. windowsにもSSHログイン出来るようになる。

書いてたらきりがない。とにかく使ってみて。

一年間のCygwinで楽しんだまとめです。そしてCygwinのお陰でMacターミナルで困らなくなってCygwinには感謝してる。

1つずつ振り返っていく。


とその前に、まずコレだけは知っておくべき。

昔のCygwinはとても面倒臭いイメージがあり敬遠していました。ところが

1.7は、新しいCygwin

Cygwin1.5のイメージでいまのCygwinを語るべきではない

レジストリ使わない。
UTF-8になって最強。

詳しくはこっちを参照

・マウントポイントの情報をレジストリに格納しないようにした。代わりに /etc/fstab と /etc/fstab.d/$USER を使う。(ry

・ファイル名が現在の文字集合で表現できないならば、その文字は Ctrl-N + UTF-8 表現に変換される。これにより、現在の文字集合 (codepage) では正しく表現できないファイルにさえアクセスできるようになる。常に UTF-8 を使った正しい文字列を持つためには、環境変数 $LANG, $LC_ALL または $LC_CTYPE に正しい POSIX の値をセットすれば良い。

誰も知らなかった Cygwin 1.7 - BOOLEANLABEL

Cygwinの便利さを主張していく

一年間のCygwinの感動や便利さを振り返りながら、Cygwinの魅力を主張したい。

ターミナルが綺麗。

・半透明Windowが綺麗。Operaは背景。

半透明の設定の細やかさが素敵

・フォントが綺麗。
コマンドプロンプト画面の汚いMSゴシックにバイバイ

写真はM2+ipaフォント


WindowsVista/7のGlassデザインにもできる


文字化け知らず

bashに書くだけでUTF-8が使える。CygwinSjisのイメージでしたがいまや、UTF-8です。


・ファイルがUTF−8
・コマンドの全部の入出力をUTF-8にできる。
・cmd.exeでsjisi使ってた頃には考えられない便利さ。

Cygwinをインストールしたらまず、utf-8を有効にする。
echo "export LANG=ja_JP.utf8" >>  ~/.bashrc
source ~/.bashrc

これでWindowsのファイル”名”がUTF-8で扱える。

でも、pingが化けるので対策。
Cygwin(msys)のUTF-8環境便利にするコマンドラッパー - ブックマクロ開発に

/usr/local/bin/ping
#!/usr/bin/env ruby
KCODE='u'
require "kconv"
cmd = File.basename(__FILE__) +".exe " + $*.join('  ')
IO.foreach("| #{cmd} 2>&1 "){|line|puts line.kconv(Kconv::UTF8,Kconv::SJIS)}

それでも困る場合はnkfが使える。cygwinにNKFが無い。 - ブックマクロ開発に
これだけあればもう困らない。

Linuxのコマンドはほぼ使える。

linuxで便利なコマンドは大抵あります。ls / grep / find / xargs /bash / awk / csplit /split /cat /・・・とにかくほとんど使える。足りないものは諦めるしかないけど。基本的なものは全てある。

環境依存で使えなさそうなものも、実は使える

passwdでWindowsパスワードと連携するらしいぞ(使ったこと無いけど)


SSHが便利

シェル環境と、文字コードが整ったら、つぎはSSH。これがとてつもなく武器になりました。

  • sshがそのまま使えます。
  • scpでファイル転送が可能になりました。
  • rsyncでファイルも転送できます。

もうPutty・Teraterm/Poderosa要りません。

rsyncでファイル転送できるようになるので、殆どの作業がターミナルで完結するようになった。


レジストリ読むのが便利。

レジストリを読み出すだけにとても便利。ちょっとあれどうなってたっけ。って値をREADするだけなのに、regeditだとUAC求められて困る。
でもCygwinなら簡単。読み出し可エントリを順々に読むだけならとても便利。

レジストリファイルシステムにマウントされてるように扱える。

読み込みは普通のディレクトリをたどるだけ。

Cygwinだとレジストリたどるのがものすごく楽 - ブックマクロ開発に

takuya@letsnote:~$ ls /proc/registry/
HKEY_CLASSES_ROOT    HKEY_CURRENT_USER   HKEY_PERFORMANCE_DATA
HKEY_CURRENT_CONFIG  HKEY_LOCAL_MACHINE  HKEY_USERS

ls できるんですよねー

レジストリの書き込みは、

regtoolなどのツールを使う。

GNUコマンドなど便利コマンドが簡単に入る。

setup.exe面倒なんですよね。ってときには、apt-cygでCygwinでもApt/yumっぽくインストールができるようになる。。 - ブックマクロ開発に

apt-cygで:検索→インストール
入れたいパッケージを検索して、インストールします。
apt-cyg find パッケージ名
apt-cyg install パッケージ名

ターミナルで完結します。

たとえば、git /hg などもこれをベースにしてどんどん入っちゃう。楽です。
しかも git / hg がUTF-8なので文字化け知らず。嬉しい。


javacなくても大丈夫。

各種コンパイラが付いているのでシンタックスチェックくらいならすぐ出来る。
たとえば、Javaのために大量にインストール面倒くさいし、シンタックスチェックくらいならGCJでできる。

授業の課題程度なら軽快でいい

takuya@letsnote:~$ gcj-3.exe -C Test.java

http://d.hatena.ne.jp/takuya_1st/20110613/1307994985

結構使える。

Vimとか便利になる。

ここまでで
SSH経由でファイルが取得できるようになる。
・ファイル名が化けない。
文字コードも安心。
コンパイラやシンタックスチェックが出来る

ここまでとなると、Vimも動かしてgVimがわりに使いたくなる。。コーディング作業しても大丈夫ですよね。
コマンドプロンプトVimよりは相当綺麗で見やすいです。

Mintty+Vimだけで相当使い込めるVim環境が出来上がる

vimdiff やら vim256 カラーも使えるようになる。色が綺麗とは素晴らしい。

vimはttymouseなどをつけることで、gvimと変わらない性能がWindowsローカル出せるようになる。

ファイルパスの扱いも困らない。

それでもよく聞くのが、ファイルパスの扱い。

「バックスラッシュがねぇbashのエスケープじゃん?」

と言われた。でもそれ実はあまり気にしなくていい。


WindowはC:/Users/takuyaでもC:¥Users¥takuyaでも同じ。

だから困らない。

どうしても必要なときは変換すれば良い。専用のパス変換コマンドも付いている。

cygpathコマンドでWin<->cygのパス変換できる。

takuya@letsnote:~$ cygpath -w /home/takuya
C:\Users\takuya

同じってのを更に詳しく。

そもそもwindowsってシステムディスクのパス名は省略できるので、これらがが同じ

c:\users\takuya
c:/Users/takuya
/users/takuya

も同じなんですよね。Windowsは最初から、パスは柔軟でいいんです。

CygwinRubyなら、どれでも好きな様に使える。

cygwinrubyからファイルを開く時は、次のどれでもすべて同じ事になる。

open "/Users/takuya/test.dat"
open "~/test.dat"
open "C:/Users/takuya/test.dat"
open "/cydrive/c/users/takuay/test.dat"
open "C:\\users\\takuay\\test.dat"

これらは、全部 * 同じ * です。

/cygdrive が気持ち悪いなら見ないでいい。便利ですね


くわしくは、
cygpath の便利なオプション - ブックマクロ開発に

SambaのNASも簡単よ。

パスの扱いがとても綺麗なのは、ローカルファイルに限ったわけでなくSambaパスも同じ。

cd //192.168.2.10/share/takuya

すごいねー。

結論、パス名は適当でいいのです。コマンドプロンプトより使いやすいよ。

これを最初に覚えれば捗る→" cygpath -ua "です。



Windowsディレクトリ任意のマウントできるよ。

Linuxのマウントと、Windowsフォルダの関連付けは、べつにデフォルト/cygdrive にこだわらなくてもいい。
LinuxほHomeがいいって僕みたいな、変人は
Cygwinを使ってWindowsのHomeとLinuxっぽくHomeを共有する - ブックマクロ開発に
fstab書いてこんなコトした。

  5 C:/Users/ /home/ ntfs  override,binary,auto 0 0
  6 C:/Users/takuya /home/takuya ntfs  override,binary,auto 0 0

これをかけば

/home        ====> C:\Users\
/home/takuya ====> C:\Users\takuya

になる。Linuxシェル環境と同じなのでシェルスクリプト使いまわせた

半角スペースのフォルダ名にも悩まされない

fstabでマウントしちゃえば、解決。

僕はmklinkで, c:\Program files ← C:\programfilesにシンボリック・リンクしている。

これで安心ね。

sudo のあつかい

sudoも欲しくなる。最初の頃は sudo.jsとかUACダイアログを出す、コマンドラッパ書いてたんだけど、メンテがめんどくさなったので。
http://www.howtogeek.com/howto/windows-vista/sudo-for-windows-vista/

これを使って

sudo cmd.exe 

実行してUAC制御下でCygwinしてる。

sudo "cmd.exe  -k mklink"

をやって、mklinkとか使う。
シンボリック・リンクはwindows提供のものを使うべき、Gnuのlnとは別物なので、困ります。でもmklinkでシンボリック・リンクつくれる
http://d.hatena.ne.jp/takuya_1st/20110830/1314683020
http://d.hatena.ne.jp/takuya_1st/20110705/1309896867

fdiskあるよ。

fdiskコマンドもあります。ダミーファイル作って遊べます。ddと組み合わせて遊べる。

MacのOpenコマンドに負けない

cygstartコマンドがMacのOpenに相当します。

cygstart . #エクスプローラー起動
cygstart test.txt # エディタ起動

alias open=cygstart で超便利。

cygwinでサーバー起動できる

cygwinでWindowsにSSHサーバーを立てたらはかどった。
reboot コマンド呼んだり、何かと便利。

まとめ

Cygwinで生活が楽になった。

もうcygwinのないWindowsは考えられない。コマンドやGnu bashや、 mingwよりCygwin一本で完成された環境が手に入るので便利だ。


Opera / EmEditor / Cygwin / LDAP とマイナーなものを愛する私。Cygwinは手になじむツールになりました。

ただし

コンパイルしちゃいけない。なれないうちはCygwinでコンパイルは辞めたほうがいい。もしやるならCorei7マシンを用意しておくこと。Core2でもかなり時間を無駄にするので絶対にオススメしない。