Jika saya memanggil perintah menggunakan sistem Kernel # di Ruby, bagaimana saya mendapatkan hasilnya?
system("ls")
Jika saya memanggil perintah menggunakan sistem Kernel # di Ruby, bagaimana saya mendapatkan hasilnya?
system("ls")
Jawaban:
Saya ingin sedikit memperluas & memperjelas jawaban kekacauan .
Jika Anda mengelilingi perintah Anda dengan backticks, maka Anda tidak perlu (secara eksplisit) memanggil sistem () sama sekali. Backtick menjalankan perintah dan mengembalikan output sebagai string. Anda kemudian dapat menetapkan nilai ke variabel seperti:
atau
sumber
ls #{filename}
.command 2>&1
Ketahuilah bahwa semua solusi tempat Anda meneruskan string berisi nilai yang diberikan pengguna
system
,%x[]
dll. Tidak aman! Tidak aman sebenarnya berarti: pengguna dapat memicu kode untuk berjalan dalam konteks dan dengan semua izin program.Sejauh yang saya bisa katakan
system
danOpen3.popen3
berikan varian aman / melarikan diri di Ruby 1.8. Di Ruby 1.9IO::popen
juga menerima array.Cukup berikan setiap opsi dan argumen sebagai array ke salah satu panggilan ini.
Jika Anda tidak hanya perlu status keluar tetapi juga hasil yang mungkin ingin Anda gunakan
Open3.popen3
:Perhatikan bahwa form blok akan secara otomatis menutup stdin, stdout dan stderr- jika tidak mereka harus ditutup secara eksplisit .
Informasi lebih lanjut di sini: Membentuk perintah sanitary shell atau panggilan sistem di Ruby
sumber
gets
panggilan harus melewati argumennil
, karena kalau tidak kita hanya mendapatkan baris pertama dari output. Jadi misalnyastdout.gets(nil)
.Open3.popen3
tidak ada masalah besar: Jika Anda memiliki subproses yang menulis lebih banyak data ke stdout daripada yang bisa ditampung oleh pipa, subproses ditundastderr.write
, dan program Anda macetstdout.gets(nil)
.Sekadar catatan, jika Anda menginginkan keduanya (hasil dan operasi) Anda dapat melakukannya:
sumber
output=`ls no_existing_file 2>&1`; result=$?.success?
Cara mudah untuk melakukan ini dengan benar dan aman adalah dengan menggunakan
Open3.capture2()
,Open3.capture2e()
atauOpen3.capture3()
.Menggunakan backtick ruby dan
%x
aliasnya TIDAK AMAN DI BAWAH KEADAAN APAPUN jika digunakan dengan data yang tidak terpercaya. Ini BERBAHAYA , polos dan sederhana:The
system
fungsi, sebaliknya, lolos argumen benar jika digunakan dengan benar :Masalahnya adalah, ia mengembalikan kode keluar daripada output, dan menangkap yang terakhir berbelit-belit dan berantakan.
Jawaban terbaik di utas ini sejauh ini menyebutkan Open3, tetapi bukan fungsi yang paling cocok untuk tugas tersebut.
Open3.capture2
,capture2e
dancapture3
bekerja sepertisystem
, tetapi mengembalikan dua atau tiga argumen:Menyebutkan lain
IO.popen()
. Sintaksnya bisa canggung dalam arti bahwa ia menginginkan sebuah array sebagai input, tetapi ia juga berfungsi:Untuk kenyamanan, Anda dapat membungkus
Open3.capture3()
suatu fungsi, misalnya:Contoh:
Menghasilkan sebagai berikut:
sumber
require 'open3'; output = Open3.popen3("ls") { |stdin, stdout, stderr, wait_thr| stdout.read }
Perhatikan bahwa formulir blok akan secara otomatis menutup stdin, stdout dan stderr- jika tidak mereka harus ditutup secara eksplisit .capture2
,capture2e
dancapture3
juga menutup mereka std * s secara otomatis. (Paling tidak, saya tidak pernah mengalami masalah pada akhirnya.)Open3#popen2
,popen2e
danpopen3
dengan blok yang telah ditentukan: ruby-doc.org/stdlib-2.1.1/libdoc/open3/rdoc/…Anda dapat menggunakan sistem () atau% x [] tergantung jenis hasil yang Anda butuhkan.
system () mengembalikan true jika perintah ditemukan dan dijalankan dengan sukses, false sebaliknya.
% x [..] di sisi lain menyimpan hasil perintah sebagai string:
Th blog posting oleh Jay Fields menjelaskan secara rinci perbedaan antara menggunakan sistem, exec dan% x [..].
sumber
Jika Anda perlu menghindari argumen, di Ruby 1.9 IO.popen juga menerima larik:
Di versi sebelumnya, Anda dapat menggunakan Open3.popen3 :
Jika Anda juga harus lulus stdin, ini harus bekerja di 1.9 dan 1.8:
sumber
Anda menggunakan backticks:
sumber
ruby -e '%x{ls}'
- perhatikan, tidak ada output. (fyi%x{}
setara dengan backticks.)sh
akan menggemakan output ke konsol (yaitu STDOUT) serta mengembalikannya. Ini tidak.Cara lain adalah:
Perhatikan bahwa karakter "pipa" sebelum "ls" di buka. Ini juga dapat digunakan untuk memasukkan data ke dalam input standar program serta membaca output standarnya.
sumber
Saya menemukan bahwa yang berikut berguna jika Anda membutuhkan nilai kembali:
Saya secara khusus ingin membuat daftar semua proses Java pada mesin saya, dan menggunakan ini:
sumber
Seperti yang dijelaskan Simon Hürlimann , Open3 lebih aman daripada backticks dll.
Perhatikan bahwa form blok akan secara otomatis menutup stdin, stdout dan stderr- jika tidak mereka harus ditutup secara eksplisit .
sumber
Meskipun menggunakan backticks atau popen sering kali adalah yang Anda inginkan, itu sebenarnya tidak menjawab pertanyaan yang diajukan. Mungkin ada alasan yang sah untuk menangkap
system
keluaran (mungkin untuk pengujian otomatis). Googling kecil muncul jawaban yang saya pikir saya akan posting di sini untuk kepentingan orang lain.Karena saya memerlukan ini untuk menguji contoh saya menggunakan pengaturan blok untuk menangkap output standar karena
system
panggilan sebenarnya dikubur dalam kode yang sedang diuji:Metode ini menangkap setiap output di blok yang diberikan menggunakan tempfile untuk menyimpan data aktual. Contoh penggunaan:
Anda dapat mengganti
system
panggilan dengan apa pun yang panggilan internalsystem
. Anda juga bisa menggunakan metode serupa untuk menangkapstderr
jika Anda mau.sumber
Jika Anda ingin output diarahkan ke file menggunakan
Kernel#system
, Anda dapat memodifikasi deskriptor seperti ini:redirect stdout dan stderr ke file (/ tmp / log) dalam mode tambahkan:
system('ls -al', :out => ['/tmp/log', 'a'], :err => ['/tmp/log', 'a'])
Untuk perintah yang berjalan lama, ini akan menyimpan output secara real time. Anda juga dapat, menyimpan output menggunakan IO.pipe dan mengalihkannya dari sistem Kernel #.
sumber
Sebagai pengganti sistem langsung (...), Anda dapat menggunakan Open3.popen3 (...)
Diskusi lebih lanjut: http://tech.natemurray.com/2007/03/ruby-shell-commands.html
sumber
Saya tidak menemukan ini di sini sehingga menambahkannya, saya punya beberapa masalah untuk mendapatkan hasil lengkap.
sumber: http://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html
sumber
sumber