syscall - Rubyからシェルコマンドを呼び出す




ruby syscall (14)

Perlと同様に、バッククォート演算子( `)を使うこともできます。

directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory

簡単なものが必要な場合に便利です。

どの方法を使用したいかは、まさにあなたが達成しようとしていることによります。 さまざまな方法の詳細についてはドキュメントを確認してください。

Rubyプログラムの中からシェルコマンドを呼び出すにはどうすればいいですか? どうやってこれらのコマンドの出力をRubyに戻すのですか?


あなたが本当にBashを必要としているならば、「最良の」答えの中のメモに従って。

まず、Rubyがシェルを呼び出すとき、通常はBashでは なく /bin/sh 呼び出します。 一部のBash構文は、すべてのシステムの /bin/sh でサポートされていません。

Bashを使用する必要がある場合は、目的の呼び出しメソッドの内側に bash -c "your Bash-only command" 挿入します。

quick_output = system("ls -la")

quick_bash = system("bash -c 'ls -la'")

テストする:

system("echo $SHELL") system('bash -c "echo $SHELL"')

あるいは、既存のスクリプトファイル( script_output = system("./my_script.sh") )を実行している場合、Ruby shebang 尊重する 必要 がありますが、 system("bash ./my_script.sh") を使用して確認できます。 /bin/sh 実行して /bin/bash からわずかなオーバーヘッドがあるかもしれませんが、おそらく気付かないでしょう。


この説明は私の友人からのコメント付き Rubyスクリプトに 基づいています。 スクリプトを改良したい場合は、リンクから自由に更新してください。

まず、Rubyがシェルを呼び出すとき、通常はBashでは なく /bin/sh 呼び出します。 一部のBash構文は、すべてのシステムの /bin/sh でサポートされていません。

シェルスクリプトを実行する方法は次のとおりです。

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` 、一般的にはバック `cmd` と呼ばれます - `cmd`

    これは、Bash、PHP、Perlなど、他の多くの言語と同じです。

    シェルコマンドの結果を返します。

    ドキュメント: http://ruby-doc.org/core/Kernel.html#method-i-60 : http://ruby-doc.org/core/Kernel.html#method-i-60

    value = `echo 'hi'`
    value = `#{cmd}`
  2. 組み込み構文、 %x( cmd )

    x 文字の後には区切り文字があり、これは任意の文字にすることができます。 区切り文字が ([{ 、または < いずれかの文字である場合、リテラルは、ネストされた区切り文字のペアを考慮して、一致する終了区切り文字までの文字で構成されます。区切り文字の次の出現文字列補間 #{ ... } が許されます。

    バッククォートと同じように、シェルコマンドの結果を返します。

    ドキュメント: http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html : http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

    value = %x( echo 'hi' )
    value = %x[ #{cmd} ]
  3. Kernel#system

    与えられたコマンドをサブシェルで実行します。

    コマンドが見つかり正常に実行された場合は true 、それ以外の場合は false 返します。

    ドキュメント: http://ruby-doc.org/core/Kernel.html#method-i-system : http://ruby-doc.org/core/Kernel.html#method-i-system

    wasGood = system( "echo 'hi'" )
    wasGood = system( cmd )
  4. Kernel#exec

    与えられた外部コマンドを実行して現在のプロセスを置き換えます。

    noneを返します。現在のプロセスは置き換えられ、続行されません。

    ドキュメント: http://ruby-doc.org/core/Kernel.html#method-i-exec : http://ruby-doc.org/core/Kernel.html#method-i-exec

    exec( "echo 'hi'" )
    exec( cmd ) # Note: this will never be reached because of the line above

ここにいくつかの追加のアドバイスがあります: $CHILD_STATUS と同じで、バッククォート、 system() または %x{} を使用すると、最後に実行されたコマンドのステータスにアクセスします。 その後、 exitstatus プロパティと pid プロパティにアクセスできます。

$?.exitstatus

詳しくは、以下を参照してください。


これがRubyでシェルスクリプトを実行することについての私の意見の中で最も良い記事です:「 http://tech.natemurray.com/2007/03/ruby-shell-commands.html 」。

出力を取得するだけでよい場合は、バッククォートを使用します。

私はOpen4 gemを使ったので、STDOUTやSTDERRのようなもっと高度なものが必要でした。 あなたはそこで説明されたすべての方法を持っています。


これらのメカニズムの間で選ぶとき考えるべきいくつかの事柄は次のとおりです:

  1. あなたはただstdoutを望みますか、それともstderrも必要ですか? それとも離れて?
  2. あなたの出力はどれくらい大きいですか? 結果全体をメモリに保持しますか?
  3. サブプロセスがまだ実行されている間に、出力の一部を読みますか?
  4. 結果コードが必要ですか。
  5. あなたはプロセスを表し、あなたがそれを要求に応じて殺すことを可能にするルビーオブジェクトが必要ですか?

単純なバッククォート( ``)、system()、そして IO.popen から、 IO.popenIO.popenIO.popen た本格的な Kernel.fork / Kernel.exec まで、何でも必要 IO.select

サブプロセスの実行に時間がかかりすぎる場合は、タイムアウトを混在させることもできます。

残念ながら、それは非常に大きく 異なり ます。


もう一つの選択肢:

あなたが:

  • 標準出力だけでなく標準エラーも必要
  • Open3 / Open4は使えない/使わない(私のMacではNetBeansで例外が発生しますが、理由はわかりません)

シェルリダイレクションを使うことができます。

puts %x[cat bogus.txt].inspect
  => ""

puts %x[cat bogus.txt 2>&1].inspect
  => "cat: bogus.txt: No such file or directory\n"

2>&1 構文は、MS-DOSの初期の頃から、 Linux 、Mac、および Windows


上記の答えはすでに非常に優れていますが、「 http://tech.natemurray.com/2007/03/ruby-shell-commands.html 」という要約記事を共有したいと思い http://tech.natemurray.com/2007/03/ruby-shell-commands.html

基本的に、それは私たちに告げます:

Kernel#exec

exec 'echo "hello $HOSTNAME"'

system$?

system 'false' 
puts $?

バッククォート( `):

today = `date`

IO#popen

IO.popen("date") { |f| puts f.gets }

Open3#popen3 - stdlib:

require "open3"
stdin, stdout, stderr = Open3.popen3('dc') 

Open4#popen4 - 宝石:

require "open4" 
pid, stdin, stdout, stderr = Open4::popen4 "false" # => [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]

例えばattribのようなコマンド

require 'open3'

a="attrib"
Open3.popen3(a) do |stdin, stdout, stderr|
  puts stdout.read
end

私は、この方法はsystem( "thecommand")やbackticksのthecommandほど記憶に残るものではありませんが、他の方法と比較してこの方法について良いことを思い出してください。 '実行するコマンド実行するコマンドを変数に格納し、system( "thecommand")を実行しても出力が得られないようです。 この方法で私はそれらのことの両方をすることができます、そしてそれは私がstdin、stdoutおよびstderrに独立してアクセスすることを可能にします。

https://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html

http://ruby-doc.org/stdlib-2.4.1/libdoc/open3/rdoc/Open3.html


指定したコマンドを実行するためのバックグラウンドプロセスを作成する spawn コマンドを忘れないでください。 Process クラスと返された pid を使って、その完了を待つこともできます。

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

このメソッドは #system 似てい #system が、コマンドが終了するのを待ちません。


最も簡単な方法は、たとえば次のとおりです。

reboot = `init 6`
puts reboot

私たちはそれを複数の方法で達成することができます。

Kernel#exec を使用して、このコマンドが実行された後は何もしません。

exec('ls ~')

backticks or %x を使用

`ls ~`
=> "Applications\nDesktop\nDocuments"
%x(ls ~)
=> "Applications\nDesktop\nDocuments"

Kernel#system commandを使用して、成功した場合は true 、失敗した場合は false を返し、コマンドの実行が失敗した場合は nil を返します。

system('ls ~')
=> true

私のお気に入りは Open3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }

これはこの答えに 基づいたフローチャートです。 script を使用して端末をエミュレートする も参照してください。


  • backticks `methodは、Rubyからシェルコマンドを呼び出す最も簡単なものです。 シェルコマンドの結果を返します。

     url_request = 'http://google.com'
     result_of_shell_command = `curl #{url_request}`




interop