読者です 読者をやめる 読者になる 読者になる

MogLog

メモというか日記というか備忘録というか

2015年の振り返り

少し時間が経ってしまったが、以前自分が書いた振り返りブログを見返すと当時のことを鮮明に思い出せて「ああ、こんなこともあったなぁ。こんな感想持っていたのかー。」という感じになっておもしろかったので、2015年分の振り返りも書くことにした。

時系列に沿いつつ、特に印象に残ったテーマ単位で振り返る。

古くなり手を付けられなくなったレガシーコードの大幅リファクタリング

開発から年数が経ち、日に日に複雑化してレガシーコードと化してしまった検索系APIの大幅なリファクタリング(のための準備)を行った。

というような状態で、手を付けられる状態ではなくなっていた。開発者も何が影響してバグを生み出すかわからないから手を出したくない。 しかしこのAPI、サービスにとってかなり重要な機能を提供していたため、企画さんや営業さんから絶え間なく機能追加要望が来ているという状況だった。

これは良くないということで、チームメンバーで相談し合い、多少時間がかかっても良いからリファクタリングをすることに決めた。それが将来的に見てプラスになると判断した。

自分が担当したのは、最初にこのAPIの仕様を正確に把握してテストに落とすことだった。 APIなのでviewまわりの処理を気にする必要が無かったが、受け取るパラメータが80個(!)くらいあって「ウッ..」っとなった記憶がある。

あまりテストを書いた経験が無かったので、正しいかどうかはわからないが、次のような方針でやっていくことにした。

  • ① 外側から見たAPIの仕様だけをテストにする。つまり、内部的な実装のテストではなく、API利用者の視点のテストを書いていく。
  • ② テストはリクエストパラメータ単位で書く

①は1つのメソッドが長すぎてテストに落とすのは難度が高かったのと、これから大幅にリファクタリングされることもあって単体レベルのテストを書くのは無意味だと思ったので、機能面でのテストだけを書くことにした。例えば次のようなテストである。

1. パラメータ「price_from」に100を渡すと、100円以上の結果のみが返ってくる
2. パラメータ「price_from」に100を渡し、「price_to」に1000を渡すと100円以上1000円以下の結果のみが返ってくる

②についてはそのままの意味で、受け取り可能なパラメータごとに仕様を整理してテストに落とすということ。何でも良かったのだが、何かしらグループ化できると進行状況がわかるし、開発も進めやすいと思ったのでこのルールを作った。

リファクタリングが完了する前に自分は別の部署に異動してしまったので、最終的にこのリファクタリング作業がどうなったかは実は知らないのだが、上の方針でテストを書いてみていくつか感想をまとめたい。

■ 機能テストは効果が高い
機能面でのテストは、関数など単体レベルのテストよりずっと効果が高いと思った。 現実での使われ方と同じ形でテストをするので(APIの場合、HTTPリクエストをするという形をとるので)、信頼性が高く感じた。 また、内部的な実装はどんどん変わっていくが、API自体の仕様は頻繁には変わらないので保守性の面でも良いと思う。

■ 本番の検索エンジンのデータをテストに使えたのは良かった
本番の検索エンジンとつながったAPIに対してテストをできたのは良かった。 日々更新される実際の検索インデックスに対して毎日テストをかけていると、「たまに落ちる」というテストが見つかるので、それを修正していくことでテストの品質も少しずつ上がっていったし、本番のデータでテストが通ると「本当に大丈夫そうだ」という安心感があった。

■ テストパターンを十分にカバーしきれなかった
パラメータ単位でテストを書いていったので、あるパラメータとまた別のパラメータでの組み合わせによって発生する機能の仕様を追いきれなかった。 また、HTTPリクエストをしてその結果を確認する形式のテストなので、レスポンスに直接出ないパラメータの機能をテストすることができなかった。

最後の最後までやりきれず、チームメンバーに迷惑をかけてしまったのが申し訳ない限りだが、テストやリファクタリングについて真面目に考える機会ができたのは良い経験になった。

※ この時買って参考にした書籍

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

Vim::Factory開発

2015年のはじめ頃からid:mosuke5vim::factoryの開発を始めた。

http://vimfactory.com/ f:id:mogulla3:20160111233653p:plain

はじめは、お互いインフラ・サーバ寄り技術に興味があったので、Software Designなどに掲載されていたHAProxyとかDockerとかnginx等を実際に触って遊んでいた。しかし、インフラ系技術はやはり実際に動くアプリケーションがあって使わないと面白くないし、知識も浅いままになってしまうだろうということで何らかアプリケーションを作ることにした。

目的はインフラ系技術を学ぶ上で題材になるアプリケーションを作ることだったので、自己満アプリでも何でも良いはずなのだが、やはり自分たちが作りたい・使ってみたいアプリにしたいという気持ちもある。そんな風に欲張っていたから何を作るか決めるのに時間がかかった。

ある日、id:mosuke5がさくらVPSバーチャルコンソール(?)から着想を得て、vim::factoryを開発することに決まった。何度かブレストをした中に、vimrcを簡単につくって試せるアプリはどうか、というようなネタはあったものの実現方法が全く思い浮かばず却下されていたのだが、実際に似たようなイメージで動くモノを見つけたので、そこから調べてプロトタイプを作ってみたらちゃんといい感じに動いたのでこれに決めた。

平均週1のペースで開発をしつつ、インフラ・運用まわりの仕組みはこだわりたかったのでAnsibleとかDockerとかMackerel等の面白そうな技術をどんどん取り入れた。そのため、リリースできるモノができたのは4,5ヶ月後の7月になった。

その時に報告書としてid:mosuke5が書いたブログ(誰に向けた報告書かは謎w)がいい感じにバズったのはなんとなく少し自信になったし、嬉しかった。 mosuke5.hateblo.jp

なお、vim::factoryは2016年になっても細々と機能追加やバックエンドの改善をしている。本日、pluginを試せる機能を導入した。

引っ越し

2015年の7月頃に引っ越しをした。 当初は交通の便が良く街の雰囲気も良いなと思っていた住みたいエリアがあったのだが、家賃や間取りで納得行く物件が見つからず、少しアクセスが悪い場所に引っ越すことにした。今思うともう少し慎重に選ぶべきだったなという感じ。

わりと大きめのイベントだが、特に書くことが思い浮かばないので箇条書きで感想とかを適当に書く。

  • 2階の足音が気になる。次住むとしたら最上階にしたい。
  • お金が貯まらなくなる。つらい。
  • 家事(掃除、洗濯、料理、アイロン等)は結構余裕。余裕。
  • 両親のありがたみは結構感じる。
  • モノは少ない方が色々良いと思った。と言いつつ便利道具が最近揃ってきた。
  • 独立して1人でやっていけてるのは少しだけ自信になる。

Railsアプリケーション開発

2015年の10月から部署が変わった。そこで最初に担当したのは、担当サービスのversion2開発だった(現在も進行中)。 この仕事はうまくいかないことが多く、かなり苦戦した(している)。

設計面での考慮漏れ

システム全体が様々なコンポーネントが組み合わさってできていることもあって、開発を進める中で考慮漏れ部分が何度も見つかった。 考慮漏れが発覚するたびに手直しをする、直したと思ったらやっぱり元の状態が正しかった、というようなことがあって、進捗がなかなか出なかった。

元々そのシステムをメインで担当していた人物は、自分が異動してくるとほぼ同時に退職してしまったので、そのシステムを詳しく知っている人物はいなかったのが少し痛かった。。とはいえ、もう少し詳細に設計を考えるべきだったという反省もある....。

どうやっていくのが良かったのか、未だに良い対策や方法は思い浮かんでいない。

Rails開発

Rails wayに乗りたいけど、うまく乗れないというパターンが多かった。 また、Rails wayに乗ろうとするあまりか、「Railsではこういう時どう書けばよいか」というのを調べる時間が多かった。

わかるまでひたすらググっていて、なんかダメな開発スタイルになっていた気がする。 アプリケーションの仕様そのものがRails wayにそぐわない要件だった部分もあるような気がするが、Rails自体をもっと知る必要があると痛感。

また、RailsというかActiveRecordなのだが、あまり深く考えずに基礎的な知識だけでコードを書いていると、意図通りに動作するもののパフォーマンスが出ない実装になっていることがある。

直せるところは直したが、リリースも近く未着手の部分も残っている。非常に怖い。

micro services

自分が担当したシステムは、最近よく耳にする「micro services」を参考にして、メイン部分とはは完全に独立した形態のシステムになっている(と前任者に聞いた)。

しかし、おそらくだが分離の方法があまり良くなかったのではないかと思う。 なぜかというと、このシステムはメイン部分と確実に整合性を持たせなければならないデータを扱っていて、そのために複雑な分散トランザクション処理が必要になっていたからである。

この部分はかなり苦労したが、APIが1リクエストで多くの処理をこなせるようにすることでトランザクション処理を実装しやすくすることで対応した。ただ、これが正解なのかどうかはまだわからない...。

システムを分割しWebAPIを使って連携するようなシステム構成は、トランザクション面とパフォーマンス面で気にかけることが多くなるので慎重に設計した方が良いのではないか、という学びはあった。

なお、 この辺の苦悩については次のエントリでも書いている(愚痴っている)。 sandragon.hatenablog.com sandragon.hatenablog.com sandragon.hatenablog.com

勉強や学習の方向性について考え始める

エンジニア視点で、次のようなことを考えるようになった。

  • 何か1つ、得意分野を持ちたい
  • 基礎や仕組みといったすぐには廃れない、応用の効く知識を蓄えたい。「○○の使い方」等を身につけたところで、長期的にはあまり役に立たない。

この辺りに関して、過去に少しまとめたのがこの記事。 qiita.com

こうは思いつつも、仕事をしているとやっぱりハウツー系の知識が必要とされる場面が多く、実現はできていない。 たまに暗号化技術とかTCP/IPとか長く活きて多方面で役立ちそうな技術の勉強をしてみるものの、緊急で調べたいことが出てくるとそこで終わったり...。

しかし、新卒1, 2年目はインフラからフロントまで何でもできる、いわゆるフルスタックエンジニアになりたいとか言っていた気がするので、すごい変化である。

まとめ

随分長い記事になってしまった。 また数年後の自分が見ておもしろいと感じられると良いと思う。 来年は英語(特に英会話)を頑張りたい気持ちあるけど、避けられない事情があるわけでもないので、モチベーションが続くかどうかが不安です。

DBとかパフォーマンスとか

チラ裏です。

そのカラムにインデックスを張るべきか否か、そしてそれはどう判断すべきなのか

  • かなり頻繁にwhere句として使われる
  • カーディナリティは極端に小さい(現状2パターンしか無い。直近増える予定もない)

...というカラムがあった。時間が無いなりに調べた結果、このカラムにはindex不要だと思い貼らないことにした。 これを、理論からだけじゃなくて実際の測定値から判断したかったなと。

とはいえ、開発環境のテストデータで測定してもあまり意味ないだろうし、どうやるのが良いかわからなかった。本番に投入して様子見するしかないのかなー。

migrationでしくじったがどうするのが良かったんだろう

インデックスを張るか悩んだカラムだが、最初はインデックス張る方向で進めておりその設定を書いたmigrationファイルをpushしていた。さらに、試験環境にrake db:migrateしていた。

しょうがないので、indexを削除するmigrationファイルをpushしたわけだが、これ大丈夫なんかな...。 rake db:migrateすると、index作ってまたすぐ削除することになると思われるので、本番環境のDBに実行した時にどのくらい影響あるんだろってのが少し気になってる。

Railsとパフォーマンス

Rails...、というかActiveRecord。 コールバックとか関連とか、ウェッブアプリ開発で最高便利な機能をたくさん持つ代わりに、用途によってはパフォーマンスが出にくいというのが今回の開発で思ったこと。

知らないだけってのもあるだろうけど、特に書き込みが多いアプリケーションとActiveRecordって相性悪いんじゃないかと思った。大量のINSERTを1クエリにまとめるactiverecord-importや、UPDATE句をまとめるupdate_all、DELETE句をまとめるdelete_allなどはあるものの、それなりに制約があった。ActiveRecordの機能が十分に使えなくなってしまう。

実際、その制約が理由でこれらの機能をうまく導入できなかったりもした。 大量書き込みって時点でRails way外れてんのかなぁ〜

詰まったことリスト2

sandragon.hatenablog.com

これの続き。 よくもまあここまで詰まりポイントがボンボン出てくるもんだと自分の無能っぷりに呆れてきたところです。 この無能感を越え、強くなりたい。

activerecord-importの罠

activerecord-importはINSERTのクエリを1SQLにまとめて実行してくれるGem。 「Rails insert 高速化」とかで検索するとこのactiverecord-importの記事がわんさか出てくる。

このGemを使うと、たしかに何発も実行されていたSQLが1つにまとまってくれるが、INSERTして作られたレコードのidを返却してくれない。正確には特定のDBでしか返してくれない。

なんでや、ワイはidが欲しいんや!

users = []
parames.each do |param|
  users << User.new(param)
end

User.import(users) # => failed_instances、num_inserts、idsの3つのメンバを持つStructオブジェクトが返ってくる。しかし何度やってもidsメンバは空配列。

自分はMySQLを使っていたのだが、MySQLでは返してくれない情報のようだった。
「まじかよ〜」という気持ちでコードを読み漁ったところ、Postgresでしか返してくれない情報だということが判明した(多分)。
※ この辺: activerecord-import/import.rb at master · zdennis/activerecord-import · GitHub

INSERT後に、登録されたレコードを扱う必要があったので諦めざるを得なかった。 結構時間費やしたので辛み。

v2移行

サービスの仕様が大きく変わるタイミングだったので、v2としてレポジトリレベルで切り分けるかどうするかを考える必要があった。

最初に設計というか全体を考えて検討して、レポジトリまで切り分ける必要はないと判断した。 新しいAPIのエンドポイントが増えるだけで、裏の仕組みは変わらなかったのでそうしたほうがスマートだと思った。

しかし、これは間違いだった。というか考慮漏れだった。 v2側の操作によって、v1側のデータまで書き換えられてしまう操作が1つあった。

少なくともDBは切り分けるのが正解だった。ていうか普通分けるだろって感じだ。 v2開発をしているとv2のことしか目に入らなくなってしまうし、当然開発中にはv2用のデータしか用意しない。

あと、システム開発は大抵最初の設計時には気づかない仕様が後から追加されたり変更されたりというのがあるので、もし最初の時点で共存ができたとしても、いつの間にか共存できない仕様になってたということもあると思う。v1との共存をするのならそこを常に意識していないといけない気がするけど、そんなのできるわけがないマンですね。

APIのコードはできていてるし、変更する箇所は参照先DBくらいなのでそこまで大変ではないけど、神経がすり減る作業になりそうだ...。

詰まったことリスト

最近、業務でRailsアプリケーション開発をしている。 が!Railsに限らずだが何かと行き詰まってばかりなので忘れないうちにこの怒りと苦しみの元となったネタどもをリストアップしておきたいと思う。

※ ほとんど単なる調査不足・知識不足が原因だと思います

ActiveRecord関連

① パフォーマンス改善のため、User.where(type:1)のようにして取得したUserオブジェクトを1SQLでまとめて削除したかった。eachで回してそれぞれdestroyとかするとオブジェクトの数だけSQLが実行されてしまう。そこで、delete_allメソッドを使おうとしたけど、delete_allだとUserモデルの関連先オブジェクトまで削除できず要件を満たせなかったので断念した。次なる策は特にない。

# controller
users = User.where(type: 1)
User.bulk_destroy(users)

# model
def self.bulk_destroy(users)
  transaction do
    users.each(&:destroy!) # これだとusersの数だけSQLが実行される
  end
end

#
# ↓ delete_allを使おう!
#

# controller
User.where(type: 1).delete_all # これだとUserと関連しているモデルまで同時に削除できなかった

② 上記と同じように、Userの登録処理も一括で行いたかった。そこで、activerecord-importというGemを使えばできるよ!という情報を得たが、同じく関連先のテーブルまで同時に更新することはできなかった

③ 更新処理も同じく、update_allを使う方法にたどり着くものの同様の理由で断念

一括操作系REST APIの設計

RESTな一括操作系APIを作ろうとしたところ、設計で色々行き詰まった。一括操作とは、1リクエストで複数のレコードが操作されることを指す。

複数のリソースをRESTで指し示す良い方法がわからなかった。そもそも複数のリソースを示そうとしている時点で間違い?
どうしたか:検索系APIのように、クエリパラメータを使って対象のリソースを指定することにした

# typeが1のUserのstatusを1に更新する
PUT /users?type=1

{
  "users": {
    "status": 1
  }
}

② PUTやDELETEでクエリパラメータを使うことになったけど、これって良いんだっけ?
どうしたか:気にしつつも使った

③ DELETEでリクエストボディ使ってるけど、これも良いんだっけ?
どうしたか:調べた感じ、推奨されないけどRFC上禁止されてるわけでもないようだったので使った。

④ StrongParameterで配列型受け取りたいときってどうすれば良いの?
どうしたか:ググったら出てきたのでそれを真似した。しかしだいぶレール踏み外した感じ。

SQL

① INSERTをしてAUTO INCREMENTで自動採番されたIDを使って、特定のカラムを更新する処理が書かれていた。こいつはパフォーマンス劣化の原因になるし、少々不吉な匂いがしたので取り除きたかった
どうしたか:がっつり改修する以外に策はない!!!!1

user = User.new(name: 'xxx', type: 1, stauts: 0)
user.save && user.update(original_id: "hoge-#{user.id}")

microservices

① 今流行のマイクロサービス的な何か。綺麗に分離できていないせいか、コンポーネント間で複雑なトランザクション処理を実装しなければならなかった。
どうしたか:WebAPIに柔軟性を持たせた。1リクエストで多くのリソースを処理できるインターフェースを持たせた。これによってトランザクション処理がいくらかやりやすくなった。

Rubocop

メソッド10行制限キツすぎワロタ
どうしたか:がんばった

② ABC size制限厳しすぎワロタ
どうしたか:がんばった

RSpec

① 文法複雑すぎでは(sharedうんたらとかletとか星の数ほどありそうなマッチャーとか)
どうしたか:書きまくってたら慣れた。

まとめ

引き続きがんばります。

ブログのデザインを変更した

新年なのでなんとなく変えてみた。 公式テーマを使いつつ、font-familyだけカスタマイズした。

YAPC::Asia Tokyo 2015に行ってきた

8/22(Fri)、8/23(Stu)の2日間、YAPC::Asia Tokyoに参加してきた。

YAPCについては、一昨年・昨年とはてブTwitterで盛り上がっているのを見ていて、一度は行ってみたいなぁと思っていたら今年が最後らしいという情報を聞きつけて勢いで申し込んだ。なので、このYAPC::Asia Tokyo 2015が自分にとっては最初で最後のYAPC(になりそう)。

参加レポートとして、印象に残っている発表についての感想を書く。

1日目(8/22)

世界展開する大規模ウェブサービスのデプロイを支える技術 - YAPC::Asia Tokyo 2015

YAPCで一番最初に聞いた発表。 会社の業務でちょうど自動デプロイの環境構築をやっていたこともあって参加した。

会社は基本的にオンプレであり、自動デプロイについてもFabricっぽい社内独自の技術を使っていたので、共感できる部分が意外と少なかったというのが本音。本発表の対象であったMiiverseAWSに乗っかっていて、紹介されていたConsulもクラウドであるからこそ活きるツールだと感じたので。

けれど、はてな任天堂の人たちも紆余曲折を経て今の環境を作り上げることができたというのがわかったし、その点がすごくリアルに感じ取れて聞いていて楽しかった。

あとは、はてながこういう形の仕事をしているとは知らなかったので驚いた。自社サービスだけやっている会社だと思っていた。

TBD - YAPC::Asia Tokyo 2015

生Matz見れた。 「YAPCなのでRubyの話は封印します」という感じでスタートしたらその数分後に「ネタ切れなので、封印を解きます」といってRubyの話をしはじめたのがおもしろかった。個人的にRubyは好きなのでありがたい展開だったw

ただ、GILとかJITコンパイラとか言語の中の話(?)になると知識不足でわからないところも多く、もったいない感じだった。この辺はもっと勉強しないとなーと思った。

Perlの上にも三年 〜 ずっとイケてるサービスを作り続ける技術 〜 - YAPC::Asia Tokyo 2015

ベストトーク賞に選ばれた発表。 トーク概要を見ておもしろそうだなーと思って軽い気持ちで参加したら、人がめちゃくちゃいてまず驚いた。立ち見がいっぱいいた。

YAPC2日全体を見ても、この発表ほど盛り上がったのは無かった気がする。納得のベストトーク賞。

内容は、フレームワークとかオブジェクト指向とか名前付けなどてんこ盛りだったが、とりあえず『オブジェクト指向入門』と『エリック・エヴァンスドメイン駆動設計』という本が最高ということがわかったので、機会があった時に買いたいと思う。

で、自分の置かれている環境と比較して思ったことをいくつか。 はてなは、組織全体で開発・運用の問題をしっかりと認識していて、解決のために日々前進している感じがして、とても良いなと思った。

自分の環境は、コードの書き方や開発スタイルとか、サービスに直接的に効果が無いとされるものをやることはあまり歓迎されない雰囲気があって、こういうのをチームぐるみで推進していくがなかなか難しい。

隣の芝生は青く見える的なアレなのかもしれないけど、うちの開発環境もなんとかしたいなぁーと思った。

esa.io - 趣味から育てたWebサービスで生きていく - YAPC::Asia Tokyo 2015

esa.ioは個人的に使っていて満足度がすごい高いので、開催前から気になっていた発表の1つ。

サービス作るまでの話とか、開発する上での工夫とか色々聞けたけど、それよりもfukayatsuさんの開発スキルとかエネルギーが半端ないな〜と思った。RubyGemsとかChrome Extensionとか一杯作ってるし、そもそもesa自体もエンジニア1人であの完成度。

おそらく、ただ自分が好きなこと・楽しいことをやっているだけのことなんだろうけど、自分はやろうと思ってもなかなかできないのでただ尊敬。 自分も立ち止まらず「試行錯誤」しながら少しずつ前進するのが大切かな。

2日目(8/23)

3分でサービスのOSを入れ替える技術 - YAPC::Asia Tokyo 2015

3ヶ月後にCMを打つことになったサービスのインフラ面を整備したときの話。 このサービス、半分幻だと思っていたBlue-Green Deploymentを実現していた。ヤバい。

ただし、Blue-Green Deploymentを実現するには色々とやることがあったようで、どちらかというとそれらを1つずつこなしていたらBlue-Green Deploymentができる環境になっていたという印象をうけた。

puppet、aws、cloud-init、cap3、consul、mackerel、fluentd、packer...などなど大量のツール・仕組みが登場したが、正直ここまでの環境を整えるのはかなりハードルが高いと思った..。3ヶ月でここまでやってしまうペパボエンジニアのみなさん、すごすぎる。

HTTP2 時代の Web - YAPC::Asia Tokyo 2015

HTTP2の話。 この発表、めちゃくちゃわかりやすくて聞き入ってしまった。

非常に客観的にHTTP2の背景・現状・これからをまとめていて、今後自分たちがどうしていくべきか考えるとてもいいきっかけになったし、HTTP2にも興味がわいた。 HTTP/1.1とHTTP/2を比較したデモも印象的で、並列リクエストができるHTTP/2はめっちゃ早かった。

Jackさんはmozaic.fmというpodcastの配信もしているようなので、HTTP2の話があれば聞いてみようと思う。

最後に

YAPC::Asia最高でした。 今までいくつかの勉強会・イベントに参加してみたけどYAPCほど満足度の高いイベントはなかった。 半分勢いで参加したイベントだったけど、勢いに身を任せて良かった。

YAPCで学べたことを知識だけで終わらせないで、業務や趣味開発に活かせるようにしていきたい。

pgrep、pkill

pgrep

  • 現在実行中のプロセスからパターンにマッチするプロセスのプロセスIDを標準出力にリストする
  • pgrep [pattern]
  • fオプションでマッチさせる範囲をコマンドライン全体にする
  • lオプションで結果にプロセス名も表示させる
  • uオプションで実行ユーザIDを指定する

使ってみる

以下のようにrubyプロセスが3つ存在したとする。

$ ps aux | grep ruby
vagrant   2461  0.0  0.3  23628  2236 pts/0    S    08:03   0:00 ruby loop.rb
vagrant   2462  0.0  0.3  23628  2244 pts/0    S    08:03   0:00 ruby loop.rb
vagrant   2463  0.0  0.3  23628  2240 pts/0    S    08:03   0:00 ruby loop.rb
vagrant   2465  0.0  0.1   8360   792 pts/0    S+   08:03   0:00 grep ruby

実験

# プロセス名でヒットさせることができる
$ pgrep 'ruby'
2461
2462
2463

# fオプションでマッチ対象をコマンドライン全体にすることができる
$ pgrep 'loop.rb'
$ pgrep -f 'loop.rb'
2461
2462
2463

# lオプションでプロセス名も表示
$ pgrep -fl 'loop.rb'
2461 ruby loop.rb
2462 ruby loop.rb
2463 ruby loop.rb

# uオプションで実行ユーザの指定もできる
$ pgrep -u root 'ruby'
$ pgrep -u vagrant 'ruby'
2461
2462
2463

pkill

  • 名前や各種属性に基づくシグナル送信
  • pgrepとほぼ同じオプションを持つ

使ってみる

以下のようにrubyプロセスが3つ存在したとする。

$ ps aux | grep ruby
vagrant   2461  0.0  0.3  23628  2236 pts/0    S    08:03   0:00 ruby loop.rb
vagrant   2462  0.0  0.3  23628  2244 pts/0    S    08:03   0:00 ruby loop.rb
vagrant   2463  0.0  0.3  23628  2240 pts/0    S    08:03   0:00 ruby loop.rb
vagrant   2465  0.0  0.1   8360   792 pts/0    S+   08:03   0:00 grep ruby

実験

$ pkill -f 'ruby'
[1]   Terminated              ruby loop.rb
[2]-  Terminated              ruby loop.rb
[3]+  Terminated              ruby loop.rb

# コマンド1つで複数のrubyプロセスを殺すことができている
$ ps aux | grep ruby
vagrant   2474  0.0  0.1   8360   796 pts/0    S+   08:07   0:00 grep ruby

参考