SlideShare a Scribd company logo
1 of 13
Download to read offline
Ruby での
外部コマンドの実行について
2019/04/10
大手町.rb #16
大手町.rb #16 「Ruby での外部コマンドの実行について」
1自己紹介
Tomoya Kawanishi a.k.a. @cuzic
エネチェンジ株式会社 チーフエンジニア
電力会社、ガス会社を切り替えるなら、エネチェンジ経由で!
一般家庭も!法人も!
Ruby関西の中の人
2019年5月11日 第86回Ruby関西勉強会
2019年7月13日 第87回Ruby関西勉強会
発表者として登壇くださる方、あとで声かけください。
大手町.rb の中の人
毎月 大手町.rb の開催を予定
東京駅、各線大手町駅から直結!
Ruby の初級者がメインターゲット
大手町.rb #16 「Ruby での外部コマンドの実行について」
今日のテーマ
Ruby での外部コマンドの実行について
外部コマンド
ruby では system コマンド
echo 、time、ruby などすべて外部コマンド
Ruby はグルー言語としてとても優秀
グルー = のり(糊)
いろんな処理をくっつけて、新しい処理を組み立てるときに
使う言語を グルー言語 と呼ぶ
すでにいろんなベンリな機能がたくさんあるわけだし、
グルー言語として、実現する方がカンタンかつ速い!
2
大手町.rb #16 「Ruby での外部コマンドの実行について」
` ` (backtick)、 %x()、%X()
`` 、%x で簡単に外部コマンドの実行結果が取得可能
3
`aws configure get aws_access_key_id`.chomp
#=> "AKIA...........A"
`git config user.name`.chomp
#=> "cuzic"
# `` と %x は式展開する
field = "user.name"
`echo #{field}"`.chomp
#=> "user.name"
%x(echo #{field}").chomp
#=> "user.name"
# %X だと式展開しない
%X(echo #{field}").chomp
#=> "#{field}"
大手町.rb #16 「Ruby での外部コマンドの実行について」
Kernel.system
外部コマンドを実行し、成功したときに真が返る
4
system("echo Hello, World!") # PATH で見つかる echo を呼ぶ
system("echo /dev/z*") # ワイルドカードも書ける。シェル経由で実行される。
system('echo –n a¥nb') # /bin/echo は bash の echo と挙動が異なる。
# 成功するときは、true が返る
system("true") #=> true
# 失敗するときは false が返る
system("false") #=> false
# ; 区切りで複数コマンド実行できる
system("echo 1 ; echo 2")
# 改行区切りでも複数コマンド実行できる
system("echo 1 ¥n echo 2")
# 該当のコマンドが実行できないときは nil が返る
system("sad") #=> nil
大手町.rb #16 「Ruby での外部コマンドの実行について」
system の高度な利用 5
# 配列で引数を渡すこともできる
system("ssh", hostname, "bash –l –c 'cd repo; bin/rails c'")
# exception: true を指定すると、 nil が返るのではなく例外を raiseする
system("sad", exception: true) #=> Errno::ENOENT (No such file or
directory - sad)
# unsetenv_others: true を指定すると、環境変数をクリアする
system("echo $HOME") # "/home/cuzic" などが表示される
system("echo $HOME", unsetenv_others: true) # 何も表示されない
# bundle exec の中で ruby コマンドを実行するときとか便利
# 第1引数で環境変数を指定できる
system({"FOO"=>"BAR"}, "echo $FOO")
# chdir オプションで子プロセスのカレントディレクトリを変更できる
# "cd /tmp; pwd" とすると、シェル経由で実行されるが、
# 下記はシェルを経由せず、実行される
system("pwd", chdir: "/tmp")
大手町.rb #16 「Ruby での外部コマンドの実行について」
Kernel.exec
exec で実行すると ruby インタプリタを置き換える
ruby で ssh を wrap したい時とかベンリ
6
STDIN.close
STDOUT.close
system("ssh production-server")
# `system': closed stream (IOError)
STDIN.close
STDOUT.close
exec("ssh production-server")
# ふつうに ssh できる!
system("ssh production-server")
puts "ssh finished" # ssh 終了後、実行、表示される
exec("ssh production-server")
puts "ssh finished" # ssh 終了してもこの行は決して実行されない
大手町.rb #16 「Ruby での外部コマンドの実行について」
shellwords
Array#shelljoin 、String#shellescape がベンリ
7
# system メソッドに配列で引数を渡す
system("ssh", hostname, "bash –l –c 'cd repo; bin/rails version'")
# String#shellescape
rails_version = "bash –l –c 'cd repo; bin/rails version'"
require 'shellwords'
rails_version.shellescape
#=> "bash¥¥ ¥¥–l¥¥ ¥¥–c¥¥ ¥¥'cd¥¥ repo¥¥;¥¥ bin/rails¥¥ version¥¥'"
# Array#shelljoin
cmdline = ["ssh", hostname, rails_version].shelljoin
#=> "ssh production-server bash¥¥ ¥¥–l¥¥ ¥¥–c¥¥ ¥¥'cd¥¥ repo¥¥;¥¥ bin/rails¥¥ version¥¥'"
# system メソッドに文字列で渡す
`#{cmdline}`
#=> "Rails 5.0.7¥n"
大手町.rb #16 「Ruby での外部コマンドの実行について」
IO.popen
IO.popen で、標準入力からの値の取得ができる
エンコーディングの指定もできる
標準エラー出力も受け取れる
8
env = {"PGUSER"=>"scott", "PGPASSWORD"=>"tiger"}
body = IO.popen(env, "psql template1", "r+") do |io|
io.puts '¥dS+'
io.close_write
io.read
end
puts body
IO.popen("nkf –s README.md", external_encoding: "CP932", &:read)
IO.popen("ls /nothing", err: %i(child out), &:read)
#=> "ls: /nothing にアクセスできません: そのようなファイルやディレクトリはあり
ません¥n"
大手町.rb #16 「Ruby での外部コマンドの実行について」
Open3.capture3
標準入力への入力、標準出力、標準エラー出力の取得が
一度にできてとてもベンリ!
環境変数の設定などもできる
9
require 'open3'
env = {"PGUSER"=>"scott", "PGPASSWORD"=>"tiger"}
sql = <<'EOD'
¥d
selct 1 + 1;
EOD
options = {stdin_data: sql}
o, e, s = Open3.capture3(env, "psql", "template1", options)
p o #=> "リレーションがありません。¥n"
p e #=> "ERROR: ¥"selct¥"またはその近辺で構文エラー¥n行 1:"
p s #=> #<Process::Status: pid 21358 exit 0>
select を typo してる!
大手町.rb #16 「Ruby での外部コマンドの実行について」
expect
PTY と expect でインタラクティブ操作も自動化できる
非常に多数の L2SW やルータを自動制御したいときとか便利
10
require 'pty'
require 'expect'
username, password, database = "scott", "tiger", "template1"
PTY.getpty("psql –U #{username} #{database}") do |i, o|
o.sync = true
i.expect(/パスワード:/) do
o.puts password
i.expect(/#{database}/) do
o.puts "¥¥d"
i.expect(/#{database}/) do |result|
puts result
end
end
end
end
大手町.rb #16 「Ruby での外部コマンドの実行について」
まとめ
Ruby での外部コマンドの実行方法についていろいろ紹介
しました
開発生産性を改善するには
・あるものは使う。つなぐ
というのが大切です
Rubyはいろんなライブラリが用意されているので
どんな状況でもたいてい自動化することができます
今日の説明が今後の開発にお役立ちできるとうれしいです
11
ご清聴ありがとう
ございました

More Related Content

What's hot

オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu
 
文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)
Hiroshi Tokumaru
 
ソースコードの品質向上のための効果的で効率的なコードレビュー
ソースコードの品質向上のための効果的で効率的なコードレビューソースコードの品質向上のための効果的で効率的なコードレビュー
ソースコードの品質向上のための効果的で効率的なコードレビュー
Moriharu Ohzu
 

What's hot (20)

golang.tokyo #6 (in Japanese)
golang.tokyo #6 (in Japanese)golang.tokyo #6 (in Japanese)
golang.tokyo #6 (in Japanese)
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使う
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
プログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコードプログラムの処方箋~健康なコードと病んだコード
プログラムの処方箋~健康なコードと病んだコード
 
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web ServiceアプリケーションAngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)
 
ソースコードの品質向上のための効果的で効率的なコードレビュー
ソースコードの品質向上のための効果的で効率的なコードレビューソースコードの品質向上のための効果的で効率的なコードレビュー
ソースコードの品質向上のための効果的で効率的なコードレビュー
 
ストリーム処理を支えるキューイングシステムの選び方
ストリーム処理を支えるキューイングシステムの選び方ストリーム処理を支えるキューイングシステムの選び方
ストリーム処理を支えるキューイングシステムの選び方
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
PHPからgoへの移行で分かったこと
PHPからgoへの移行で分かったことPHPからgoへの移行で分かったこと
PHPからgoへの移行で分かったこと
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 とPHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門
 
組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術
 
強いて言えば「集約どう実装するのかな、を考える」な話
強いて言えば「集約どう実装するのかな、を考える」な話強いて言えば「集約どう実装するのかな、を考える」な話
強いて言えば「集約どう実装するのかな、を考える」な話
 

Similar to Ruby での外部コマンドの実行について

ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
emasaka
 
20091119_sinatraを使ってみた
20091119_sinatraを使ってみた20091119_sinatraを使ってみた
20091119_sinatraを使ってみた
ngi group.
 
Itcamp長崎2012 capistrano
Itcamp長崎2012 capistranoItcamp長崎2012 capistrano
Itcamp長崎2012 capistrano
kumachang_LL
 

Similar to Ruby での外部コマンドの実行について (20)

Ruby の制御構造とリテラルについて
Ruby の制御構造とリテラルについてRuby の制御構造とリテラルについて
Ruby の制御構造とリテラルについて
 
RubyGems と Bundler について
RubyGems と Bundler についてRubyGems と Bundler について
RubyGems と Bundler について
 
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
ゲットーの斜め上をゆくWebアプリケーションフレームワークの開発
 
RubyGems と Bundler について
RubyGems と Bundler についてRubyGems と Bundler について
RubyGems と Bundler について
 
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
 
No More Noprototype Function
No More Noprototype FunctionNo More Noprototype Function
No More Noprototype Function
 
らくちん Go言語
らくちん Go言語らくちん Go言語
らくちん Go言語
 
Ilstudy001_20110806
Ilstudy001_20110806Ilstudy001_20110806
Ilstudy001_20110806
 
メタメタプログラミングRuby
メタメタプログラミングRubyメタメタプログラミングRuby
メタメタプログラミングRuby
 
Ruby – The Scripting Language
Ruby – The Scripting LanguageRuby – The Scripting Language
Ruby – The Scripting Language
 
Ruby のワンライナーについて
Ruby のワンライナーについてRuby のワンライナーについて
Ruby のワンライナーについて
 
20091119_sinatraを使ってみた
20091119_sinatraを使ってみた20091119_sinatraを使ってみた
20091119_sinatraを使ってみた
 
SocketStream入門
SocketStream入門SocketStream入門
SocketStream入門
 
Rake
RakeRake
Rake
 
ffi for rubyists
ffi for rubyistsffi for rubyists
ffi for rubyists
 
秋のVim祭り Rubyを添えて
秋のVim祭り Rubyを添えて秋のVim祭り Rubyを添えて
秋のVim祭り Rubyを添えて
 
Itcamp長崎2012 capistrano
Itcamp長崎2012 capistranoItcamp長崎2012 capistrano
Itcamp長崎2012 capistrano
 
Ruby の String のメソッドについて
Ruby の String のメソッドについてRuby の String のメソッドについて
Ruby の String のメソッドについて
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
 
running-elixir-in-production
running-elixir-in-productionrunning-elixir-in-production
running-elixir-in-production
 

More from Tomoya Kawanishi

Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーRuby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Tomoya Kawanishi
 
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Tomoya Kawanishi
 

More from Tomoya Kawanishi (20)

英単語の覚え方
英単語の覚え方英単語の覚え方
英単語の覚え方
 
ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例ENECHANGE社での Scout APM 利用事例
ENECHANGE社での Scout APM 利用事例
 
エンジニア転職のノウハウ
エンジニア転職のノウハウエンジニア転職のノウハウ
エンジニア転職のノウハウ
 
Ruby の文字列について
Ruby の文字列についてRuby の文字列について
Ruby の文字列について
 
Ruby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構についてRuby on Rails のキャッシュ機構について
Ruby on Rails のキャッシュ機構について
 
Ruby初心者からよく質問されること
Ruby初心者からよく質問されることRuby初心者からよく質問されること
Ruby初心者からよく質問されること
 
Ruby の正規表現について
Ruby の正規表現についてRuby の正規表現について
Ruby の正規表現について
 
AWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったことAWS のコスト管理をちゃんとしたくてやったこと
AWS のコスト管理をちゃんとしたくてやったこと
 
PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選PostgreSQL のイケてるテクニック7選
PostgreSQL のイケてるテクニック7選
 
HTTPと Webクローリングについて
HTTPと WebクローリングについてHTTPと Webクローリングについて
HTTPと Webクローリングについて
 
Active record query interface
Active record query interfaceActive record query interface
Active record query interface
 
Active Support のコア拡張機能について
Active Support のコア拡張機能についてActive Support のコア拡張機能について
Active Support のコア拡張機能について
 
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナーRuby ビジネス創出展 Ruby初心者向けプログラミングセミナー
Ruby ビジネス創出展 Ruby初心者向けプログラミングセミナー
 
RubyのDir、File、IO について
RubyのDir、File、IO についてRubyのDir、File、IO について
RubyのDir、File、IO について
 
Thread の利用事例紹介
Thread の利用事例紹介Thread の利用事例紹介
Thread の利用事例紹介
 
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
Ruby on Rails プロジェクトでの他言語エコシステムとの共存方法
 
マークアップで使えるRuby
マークアップで使えるRubyマークアップで使えるRuby
マークアップで使えるRuby
 
エネチェンジでの Side ci 利用事例について
エネチェンジでの Side ci 利用事例についてエネチェンジでの Side ci 利用事例について
エネチェンジでの Side ci 利用事例について
 
AWSコストの事業部別コスト配分について
AWSコストの事業部別コスト配分についてAWSコストの事業部別コスト配分について
AWSコストの事業部別コスト配分について
 
Pry による repl 駆動開発について
Pry による repl 駆動開発についてPry による repl 駆動開発について
Pry による repl 駆動開発について
 

Recently uploaded

Recently uploaded (10)

Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 

Ruby での外部コマンドの実行について

  • 2. 大手町.rb #16 「Ruby での外部コマンドの実行について」 1自己紹介 Tomoya Kawanishi a.k.a. @cuzic エネチェンジ株式会社 チーフエンジニア 電力会社、ガス会社を切り替えるなら、エネチェンジ経由で! 一般家庭も!法人も! Ruby関西の中の人 2019年5月11日 第86回Ruby関西勉強会 2019年7月13日 第87回Ruby関西勉強会 発表者として登壇くださる方、あとで声かけください。 大手町.rb の中の人 毎月 大手町.rb の開催を予定 東京駅、各線大手町駅から直結! Ruby の初級者がメインターゲット
  • 3. 大手町.rb #16 「Ruby での外部コマンドの実行について」 今日のテーマ Ruby での外部コマンドの実行について 外部コマンド ruby では system コマンド echo 、time、ruby などすべて外部コマンド Ruby はグルー言語としてとても優秀 グルー = のり(糊) いろんな処理をくっつけて、新しい処理を組み立てるときに 使う言語を グルー言語 と呼ぶ すでにいろんなベンリな機能がたくさんあるわけだし、 グルー言語として、実現する方がカンタンかつ速い! 2
  • 4. 大手町.rb #16 「Ruby での外部コマンドの実行について」 ` ` (backtick)、 %x()、%X() `` 、%x で簡単に外部コマンドの実行結果が取得可能 3 `aws configure get aws_access_key_id`.chomp #=> "AKIA...........A" `git config user.name`.chomp #=> "cuzic" # `` と %x は式展開する field = "user.name" `echo #{field}"`.chomp #=> "user.name" %x(echo #{field}").chomp #=> "user.name" # %X だと式展開しない %X(echo #{field}").chomp #=> "#{field}"
  • 5. 大手町.rb #16 「Ruby での外部コマンドの実行について」 Kernel.system 外部コマンドを実行し、成功したときに真が返る 4 system("echo Hello, World!") # PATH で見つかる echo を呼ぶ system("echo /dev/z*") # ワイルドカードも書ける。シェル経由で実行される。 system('echo –n a¥nb') # /bin/echo は bash の echo と挙動が異なる。 # 成功するときは、true が返る system("true") #=> true # 失敗するときは false が返る system("false") #=> false # ; 区切りで複数コマンド実行できる system("echo 1 ; echo 2") # 改行区切りでも複数コマンド実行できる system("echo 1 ¥n echo 2") # 該当のコマンドが実行できないときは nil が返る system("sad") #=> nil
  • 6. 大手町.rb #16 「Ruby での外部コマンドの実行について」 system の高度な利用 5 # 配列で引数を渡すこともできる system("ssh", hostname, "bash –l –c 'cd repo; bin/rails c'") # exception: true を指定すると、 nil が返るのではなく例外を raiseする system("sad", exception: true) #=> Errno::ENOENT (No such file or directory - sad) # unsetenv_others: true を指定すると、環境変数をクリアする system("echo $HOME") # "/home/cuzic" などが表示される system("echo $HOME", unsetenv_others: true) # 何も表示されない # bundle exec の中で ruby コマンドを実行するときとか便利 # 第1引数で環境変数を指定できる system({"FOO"=>"BAR"}, "echo $FOO") # chdir オプションで子プロセスのカレントディレクトリを変更できる # "cd /tmp; pwd" とすると、シェル経由で実行されるが、 # 下記はシェルを経由せず、実行される system("pwd", chdir: "/tmp")
  • 7. 大手町.rb #16 「Ruby での外部コマンドの実行について」 Kernel.exec exec で実行すると ruby インタプリタを置き換える ruby で ssh を wrap したい時とかベンリ 6 STDIN.close STDOUT.close system("ssh production-server") # `system': closed stream (IOError) STDIN.close STDOUT.close exec("ssh production-server") # ふつうに ssh できる! system("ssh production-server") puts "ssh finished" # ssh 終了後、実行、表示される exec("ssh production-server") puts "ssh finished" # ssh 終了してもこの行は決して実行されない
  • 8. 大手町.rb #16 「Ruby での外部コマンドの実行について」 shellwords Array#shelljoin 、String#shellescape がベンリ 7 # system メソッドに配列で引数を渡す system("ssh", hostname, "bash –l –c 'cd repo; bin/rails version'") # String#shellescape rails_version = "bash –l –c 'cd repo; bin/rails version'" require 'shellwords' rails_version.shellescape #=> "bash¥¥ ¥¥–l¥¥ ¥¥–c¥¥ ¥¥'cd¥¥ repo¥¥;¥¥ bin/rails¥¥ version¥¥'" # Array#shelljoin cmdline = ["ssh", hostname, rails_version].shelljoin #=> "ssh production-server bash¥¥ ¥¥–l¥¥ ¥¥–c¥¥ ¥¥'cd¥¥ repo¥¥;¥¥ bin/rails¥¥ version¥¥'" # system メソッドに文字列で渡す `#{cmdline}` #=> "Rails 5.0.7¥n"
  • 9. 大手町.rb #16 「Ruby での外部コマンドの実行について」 IO.popen IO.popen で、標準入力からの値の取得ができる エンコーディングの指定もできる 標準エラー出力も受け取れる 8 env = {"PGUSER"=>"scott", "PGPASSWORD"=>"tiger"} body = IO.popen(env, "psql template1", "r+") do |io| io.puts '¥dS+' io.close_write io.read end puts body IO.popen("nkf –s README.md", external_encoding: "CP932", &:read) IO.popen("ls /nothing", err: %i(child out), &:read) #=> "ls: /nothing にアクセスできません: そのようなファイルやディレクトリはあり ません¥n"
  • 10. 大手町.rb #16 「Ruby での外部コマンドの実行について」 Open3.capture3 標準入力への入力、標準出力、標準エラー出力の取得が 一度にできてとてもベンリ! 環境変数の設定などもできる 9 require 'open3' env = {"PGUSER"=>"scott", "PGPASSWORD"=>"tiger"} sql = <<'EOD' ¥d selct 1 + 1; EOD options = {stdin_data: sql} o, e, s = Open3.capture3(env, "psql", "template1", options) p o #=> "リレーションがありません。¥n" p e #=> "ERROR: ¥"selct¥"またはその近辺で構文エラー¥n行 1:" p s #=> #<Process::Status: pid 21358 exit 0> select を typo してる!
  • 11. 大手町.rb #16 「Ruby での外部コマンドの実行について」 expect PTY と expect でインタラクティブ操作も自動化できる 非常に多数の L2SW やルータを自動制御したいときとか便利 10 require 'pty' require 'expect' username, password, database = "scott", "tiger", "template1" PTY.getpty("psql –U #{username} #{database}") do |i, o| o.sync = true i.expect(/パスワード:/) do o.puts password i.expect(/#{database}/) do o.puts "¥¥d" i.expect(/#{database}/) do |result| puts result end end end end
  • 12. 大手町.rb #16 「Ruby での外部コマンドの実行について」 まとめ Ruby での外部コマンドの実行方法についていろいろ紹介 しました 開発生産性を改善するには ・あるものは使う。つなぐ というのが大切です Rubyはいろんなライブラリが用意されているので どんな状況でもたいてい自動化することができます 今日の説明が今後の開発にお役立ちできるとうれしいです 11