Perlからshared objectの関数を呼び出す
Perlのglobはもうshellを呼ばない
もう10年以上前の話だが、メモ。
IPAのセキュア・プログラミング講座にある4-2. Perl の危険な関数には以下の記載がある。
便利な<> 構文,glob関数であるが,実は内部的にシェルを呼び出している。そのためリスト7の1行目のような文字列を渡した場合,パスワードファイルの内容をメールで送信できてしまう。
が、これはかなーり古いPerlでの話で、pre-5.6.0のみに当て嵌まる話。現在はFile::GlobというXSで記述されたモジュールがよしなにやってくれており、cshを内部でforkすることはない。
このあたりはperldeltaに詳しい。
https://metacpan.org/pod/release/GSAR/perl-5.6.0/pod/perldelta.pod
この記述、加筆修正されないんだろうか…
PerlでGoogle Calendar APIを勉強
アラートのメール通知がきたらGoogle Calendarに記入しておくとあとで振り返るのが簡単なんじゃないかなーと思ったので、まずはお勉強から。
要素
できるようになってから振り返ると、以下の要素を理解する必要があった。
- REST
- OAuth 2.0
- Application Credential
- Authorization Code
- Scope
- Access Token
- Refresh Token
- Google Calendar API 3.0
これからそれぞれの要素について書いていこうと思う。
コードはほぼコピペだが、エラー処理(status=200でないとき)の処理は簡単のため省いている。
PerlでTwitter API SSL化に対応するたった1行
手元でTwitterの古いpostを削除するスクリプトをcron実行してるのですが、Twitter APIってSSLのみ対応になったのをすっかり放置してしまっていました。
cron実行に失敗してメール通知が来たので1週間くらい経ってようやく対応。
Net::Twitterを使っているのでバージョンを上げて、アプリ側では1行追加するだけ。
my $nt = Net::Twitter->new( traits => [qw/OAuth API::RESTv1_1/], consumer_key => $config->{consumer_key}, consumer_secret => $config->{consumer_secret}, access_token => $config->{access_token}, access_token_secret => $config->{access_token_secret}, ssl => 1, # ここを追加 ); if (!defined $nt) { die "Authentication Failed: $!"; }
無事動きました。
Parallel::Fork::BossWorkerAsyncがいい感じ
先日 id:hirose31 と
- 並列処理はParallel::ForkManagerとかParallel::Preforkが定番だけど、もうちょっと効率よくやりたいこともある
- P::ForkManagerはタスクごとにforkするので負荷の分散は綺麗にできるが、タスクの数だけforkが発生して効率がよくない
- P::Preforkだとfork回数は並列度分だけだが、タスク開始前にタスクの分配を完了させないといけない
- Cでmultithreadならmaster-workerモデルでmasterにqueue持ってmutexでロックするような練習問題とかある
- けどPerlでmultithreadやりたくないし、実現するとすればsocket経由でタスクを渡していく感じにしないといけないか
- 誰かCPANに上げてるんじゃないかなー
- なければ作るかー
的な話をしていました。
で、metacpanを漁っていたところ、それっぽいのを見付けました。Parallel::Fork::BossWorkerAsync。
計算モデル
このモジュールは事前に1個のbossとk個のworkerプロセスをforkし、masterが都度タスクを生成して登録していきます。
workerはただただwork_handlerで与えられたsubを実行していき、計算結果をreturnします。
workerの計算結果が帰ってくるとmasterではresult_handlerで与えられたsubが呼び出されます。(たとえば結果を集めるオブジェクトに登録する)
最後にshutdownを呼び出すとbossと全workerが終了します。
プロセスツリーとしてはこうなります。
└─perl,18371 bwa.pl # アプリケーション └─perl,18372 bwa.pl # boss ├─perl,18373 bwa.pl # worker ├─perl,18374 bwa.pl # worker ├─perl,18375 bwa.pl # worker ├─perl,18376 bwa.pl # worker └─perl,18377 bwa.pl # worker
bossプロセスは各workerとアプリケーションとタスク/結果のやりとりをするためにひたすらselect(2)を呼んでいるプロセスです。
workerプロセスはbossからタスクを受け取って処理したらbossに結果を返します。
アプリケーションプロセスはbossとだけ直接通信し、タスクを投げて結果を受け取ります。
利用例
大したものではないですが、podに書かれていないようなモデルでの利用例。
workerは単に1秒sleepし、自分のjob idを返します。
masterは返されたjob idを配列に追加していって最後にdumpします。
それだけ。
この例ではk=5としていて、最初に5プロセスが生まれた後はプロセスの交代は起こっていません。
タスク供給はちょっと不定期な感じにするために、17個ずつ供給し、終了次第次の17個を供給してます。
53 / 17 = 3あまり2
17個のタスクを5並列でやると4秒かかるので、
4 * 3 + 1 = 13秒で実行が完了します。
#!/usr/bin/env perl use strict; use warnings; use Parallel::Fork::BossWorkerAsync; use Data::Dumper qw(Dumper); use Time::HiRes qw(gettimeofday); my @Finished_Jobs = (); my $PARALLELISM = 5; # sleep time my $NUM_WORKS = 53; my $WORKS_AT = 17; # この時点でworkerがforkされた my $bw = Parallel::Fork::BossWorkerAsync->new( work_handler => \&work, result_handler => \&rhandler, worker_count => $PARALLELISM, ); my $thrown_work = 0; while($thrown_work < $NUM_WORKS) { my @tasks; for my $i ($thrown_work .. $thrown_work + $WORKS_AT - 1) { push @tasks, { id => $i, sleep => 1 }; $thrown_work++; if ($thrown_work >= $NUM_WORKS) { last; } } # タスク集合はここでディスパッチされる $bw->add_work(@tasks); # 実行完了待ちタスク数が得られる。この関数はblockしない while($bw->pending) { # "return"されたオブジェクトをそのまま受け取る。以下のように単に呼び出すとblocking my $ref = $bw->get_result; # P::F::BossWorkerAsyncのレイヤでエラーがハンドルされた場合は ERROR というkeyにメッセージが入ってくる(タイムアウトを指定した場合など) if ($ref->{ERROR}) { print STDERR "ERR: ". $ref->{ERROR}; } else { print $ref->{job} . "\n"; } } } # workerプロセスを終了させる $bw->shut_down; print Dumper \@Finished_Jobs; # worker側で各タスクに対してcallbackされる sub work { my ($job) = @_; my $id = $job->{id}; my $t0 = gettimeofday; print "$t0 start $id\n"; sleep $job->{sleep}; my $te = gettimeofday; print "$te end $id\n"; return { job => $id }; } # master側でタスク終了時にcallbackされる sub rhandler { my ($result) = @_; my $job = $result->{job}; push @Finished_Jobs, $job; return $result; }
内部的にData::Dumperを使ったシリアライズをしているらしく、データの区切りに決め打ちのバイト列を指定する必要があります。そこはStorable::nfreeze/thawした方がいいんじゃないかな?と思ったりはします。
P::ForkManagerやP::Preforkに比べると記述は増えますが、用途によっては便利なのでは?
Server::Starterに対応するとはどういうことか
StarletやStarmanと組み合わせてよく使われているServer::Starterですが、普段気にしないような部分を読む機会があったのでメモ。
Server::Starterは --port (TCP) や --path (Unix Domain Socket) を渡すとこれでlisten(2)して起動するworkerに引き渡してくれる。
これはfork(2)とexec(2)によってファイルディスクリプタを引き継ぐことにより実現されているが、ファイルディスクリプタそのものをどのように引き渡しているのか、という問題。
exec(2)により実行バイナリは差し換わってしまうので、プログラム中の変数により引き継ぐことはできない。
Server::Starterではこれを環境変数SERVER_STARTER_PORTにより実現している。
おおよそ以下のような感じ。
FD = integer EQ = '=' SEMICOLON = ';' SERVER_STARTER_PORT = PORT_DESCRIPTION ( SEMICOLON SERVER_STARTER_PORT ) PORT_DESCRIPTION = PORT_NAME EQ FD PORT_NAME = character+
PORT_NAMEはソケットの種類によって違って、TCPであればポート番号(8080)とかホスト名:ポート番号(localhost:8080)、Unix Domain Socketであればそのパス(/path/to/app.sock)となる。
PODにも書いてあるServer::Starter::server_portsはこの環境変数をほどいてPerlのハッシュにして返してくれる小さなサブルーチンとして実装されているので、workerがPerlであればこれを使えばよい。
workerは環境変数から受け取ったファイルディスクリプタの番号をfdopen(3)して(あるいはそれすらもせずに)そのソケットを利用することができる。
ところで別にworkerがPerlであることは要請されていない。
続きを読むYAPC::Asia 2013 Staff Report
去年の YAPC::Asia 2012にStaff参加してきた - Limitの日記 に引き続き、今年も YAPC::Asia 2013 のStaffとして参加してきました。
今年も「ブログを書くまでがYAPC::Asia」ということで、書きます。
今年は僭越ながら多目的教室2という部屋のリーダーを仰せつかり、メンバーをまとめる役割となってしまいました。
この部屋で何か問題があったら私のせいです。
Staff Kickoff
Staffは7月頃に1度集まり、kickoffという名の飲み会をやっていました。
ここでは主に顔合わせ。去年と同じく名刺交換などです。
前夜祭
実は前夜祭の前にコアスタッフと呼ばれる一部メンバーが9割方の準備を済ませてくれています(ほんとうにありがとう!)
前夜祭の日に集まったスタッフは残り1割の準備をやります。
ひたすら来場者に渡すノベルティの準備作業をしたり、椅子スポンサーの準備をしたり、会場の展示物の準備をしたり、、、
例年の前夜祭では受付の開始前にはノベルティは準備が終わるのですが、今年は分量が多く、受付開始しても準備が終わらない状態。
前夜祭の受付がバタバタしていたのはそのせいです。
それでもスタッフがいい感じに連携してTシャツを渡すことができていたので、かなりスムーズな受付になっていたと思います。
その裏では別メンバーがノベルティ詰め作業を続行していました。
受付が一段落した後もTシャツをサイズ別にトートバッグに入れ、整頓する作業が続けられました。
NOCチームはずっとNW敷設作業をしていました。
個人スポンサー/企業スポンサーの提灯のセッティングもこのあたりで。
企業スポンサーの提灯が階段上の手すりをわたるようにセットされていましたが、あれもその場のスタッフのアイデアです。
作業は施錠の21:00まで続きました。
1日目
本番初日、8:30集合、9:00開錠ということで、朝から慌ただしい感じでした。
多目的教室はこの日初めて入れるようになったので、そこから椅子スポンサーの準備、ビデオカメラ設置、電源準備、バックパネル準備などを行い、最初のセッションに備えます。
各部屋ごとに担当者のLINEグループをつくり、メンバーはそこでその部屋固有のやりとりをできるように準備。
スタッフも抜けたい時間があったり、他の会場の準備を手伝う予定ができたりするので、セッションごとに担当を割り付けます。
そのあとは各セッションでタイムキーピング、録画がされているかを確認、幕間に流すCM、発表者への説明などを行っていました。
懇親会の間には翌日に備えた細々とした準備をしたり、投票システムのチェックをしたり(実は告知前にシステムのバグを発見していました/もちろんリリース前に修正済)。
懇親会は後半だけいたのですが、ご飯おいしかったですね。
この日は懇親会の後比較的早めに作業が終わり、平和に終わりました。
2日目
この日は基本的に1日目と同じです。
LTが行われる間に大量の撤収作業が行われ、とにかく早く全てを片付ける、ということに追われていました。
ということでやはり発表はほとんど見ていません。動画に期待。
大きな物の運び出しは運送業者の方がやってくる時間が決まっているので、期限があるものからとにかく片付ける。
なかなか物は減らず、メインホールで発表が行われている間も含めて数時間にわたる撤収作業が行われていました。
Staff として。
YAPC::Asia Staff としては2年目、YAPC::Asia の参加者としては3年目でした。
去年も一緒にStaffとして仕事をした方とは相変わらず、今年からの方とも仲良くなれて、人間関係が広がったんじゃないかなと思います。
Hacker の技術をお披露目する場を作る手伝いができるって、楽しい。
実は通しで見られたセッションは2つくらいだったりしますが、その辺は後日公開の動画で補完しておきます。
今後の YAPC::Asia は?
クロージングでは今まで YAPC::Asia を主体となって運営してきて下さった牧さん、櫛井さんの引退が発表されました。
スタッフもこのとき初めて聞かされたことでした。世代交代の時期ということなのだと思います。
来年も YAPC::Asia を誰かが開催できるかどうか、わかりません。今回1000人規模でしたが、牧さん櫛井さんが抜けた結果、この規模で開催はできないかもしれません。
それでも、縮小しても開催できれば、また大きくするチャンスがあるのだと思います。
もし開催されれば、そのときはまた運営として携わってみたいです。
参加したみなさんへ
ブログを書くまでがYAPC::Asiaです。みなさん書きましょう。
書いたらYAPC::Asia 2013 感想エントリまとめ(募集中) | YAPC::Asia Tokyo 2013へ。
アンケートもメールが届いていると思うのでお願いします!
ときどきTech系イベントには参加しているので、もしどこかで見掛けたら声かけてください。
では!