1265 Stimmen

Wie man Shell-Befehle aus Ruby aufruft

Wie kann ich Shell-Befehle aus einem Ruby-Programm heraus aufrufen? Wie bekomme ich dann die Ausgabe dieser Befehle zurück in Ruby?

4 Stimmen

Diese Frage ist zwar nützlich, aber sie wird nicht gut gestellt. Ruby hat viele Möglichkeiten, Sub-Shells aufzurufen, die gut dokumentiert sind und leicht durch Lesen der Kernel y Öffnen3 Dokumentation und Suche hier auf SO.

3 Stimmen

Leider ist dieses Thema sehr komplex. Open3 ( docs ) ist die beste Wahl für die meisten Situationen, IMO, aber auf älteren Versionen von Ruby, wird es nicht respektieren eine modifizierte PATH ( bugs.ruby-lang.org/issues/8004 ), und je nachdem, wie Sie args übergeben (insbesondere, wenn Sie opts hash mit Nicht-Schlüsselwörtern verwenden), kann es zu einem Bruch kommen. Aber, wenn Sie diese Situationen treffen, dann tun Sie etwas ziemlich fortgeschritten und Sie können herausfinden, was zu tun ist, indem Sie die Implementierung von Open3 .

6 Stimmen

Ich bin überrascht, dass niemand erwähnt hat Shellwords.escape ( doc ). Sie möchten keine Benutzereingaben direkt in Shell-Befehle einfügen - geben Sie sie zuerst in einer Escape-Funktion ein! Siehe auch Befehlsinjektion .

9voto

Kashyap Punkte 13596

Wenn Sie einen komplexeren als den üblichen Fall haben, der nicht mit `` dann schauen Sie unter Kernel.spawn() . Dies scheint die allgemeinste/vollste Funktion zu sein, die Ruby zur Ausführung externer Befehle bietet.

Sie können es verwenden, um:

  • Prozessgruppen erstellen (Windows).
  • in, out, error auf Dateien/andere umleiten.
  • env vars, umask setzen.
  • vor dem Ausführen eines Befehls das Verzeichnis wechseln.
  • Ressourcenlimits für CPU/Daten/etc. festlegen.
  • Machen Sie alles, was Sie mit anderen Optionen in anderen Antworten machen können, aber mit mehr Code.

El Ruby-Dokumentation hat genügend gute Beispiele:

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (no shell)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : dont clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join to specified process group
    :pgroup => nil       : dont change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : dont create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  current directory:
    :chdir => str
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => false : inherit fds (default for system and exec)
    :close_others => true  : dont inherit (default for spawn and IO.popen)

9voto

Vaisakh VM Punkte 993

Die Backtick-Methode (`) ist die einfachste Methode, um Shell-Befehle von Ruby aus aufzurufen. Sie gibt das Ergebnis des Shell-Befehls zurück:

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

9voto

barlop Punkte 11355

Mit einem Befehl wie attrib :

require 'open3'

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

Ich habe festgestellt, dass diese Methode zwar nicht so einprägsam ist wie

system("thecommand")

o

`thecommand`

in Backticks, ein Vorteil dieser Methode im Vergleich zu anderen Methoden ist Backticks scheinen nicht zuzulassen, dass ich puts den Befehl, den ich ausführe, bzw. den Befehl, den ich ausführen möchte, in einer Variablen zu speichern, und system("thecommand") scheint mir nicht zu erlauben, die Ausgabe zu erhalten, während ich mit dieser Methode beides tun kann, und sie erlaubt mir den Zugriff auf stdin, stdout und stderr unabhängig.

Siehe " Ausführen von Befehlen in Ruby " und Die Open3-Dokumentation von Ruby .

4voto

lucaortis Punkte 420

Dies ist keine wirkliche Antwort, aber vielleicht findet sie jemand nützlich:

Wenn Sie TK GUI unter Windows verwenden und Shell-Befehle von rubyw aus aufrufen müssen, erscheint immer ein lästiges CMD-Fenster, das weniger als eine Sekunde lang auftaucht.

Um dies zu vermeiden, können Sie verwenden:

WIN32OLE.new('Shell.Application').ShellExecute('ipconfig > log.txt','','','open',0)

o

WIN32OLE.new('WScript.Shell').Run('ipconfig > log.txt',0,0)

Beide speichern die ipconfig Ausgang innen log.txt aber es wird kein Windows angezeigt.

Sie müssen require 'win32ole' innerhalb Ihres Skripts.

system() , exec() y spawn() werden bei der Verwendung von TK und rubyw alle dieses lästige Fenster öffnen.

3voto

Bei Shell-Befehlen bin ich mir nicht sicher. Ich habe folgendes verwendet, um die Ausgabe von Systembefehlen in eine Variable zu speichern val :

val = capture(:stdout) do
  system("pwd")
end

puts val

gekürzte Version:

val = capture(:stdout) { system("pwd") }

erfassen Methode wird bereitgestellt von active_support/core_ext/kernel/reporting.rb

In ähnlicher Weise können wir auch Standardfehler erfassen mit :stderr

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X