Создание системного вызова, который возвращает вывод stdout как строку

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

16
задан 12 revs, 3 users 72% 19 November 2012 в 06:00
поделиться

27 ответов

Perl:

$output = `foo`;

ДОБАВИЛ: Это - действительно многоканальная связь. Вышеупомянутое является также допустимым PHP, и Ruby, например, использует ту же нотацию обратной галочки также.

3
ответ дан 30 November 2019 в 15:01
поделиться

Python

from subprocess import check_output as qx

output = qx(['ls', '-lt'])

Python < 2.7 или < 3.1

Извлечение subprocess.check_output() от subprocess.py или адаптируют что-то подобное:

import subprocess

def cmd_output(args, **kwds):
  kwds.setdefault("stdout", subprocess.PIPE)
  kwds.setdefault("stderr", subprocess.STDOUT)
  p = subprocess.Popen(args, **kwds)
  return p.communicate()[0]

print cmd_output("ls -lt".split())

подпроцесс модуль был в stdlib с тех пор 2.4.

20
ответ дан 30 November 2019 в 15:01
поделиться

Предоставленный, это не меньшее (со всех доступных языков), но не должно случаться так что подробное.

Эта версия грязна. Исключения должны быть обработаны, чтение может быть улучшено. Это должно только показать, как версия Java могла запуститься.

Process p = Runtime.getRuntime().exec( "cmd /c " + command );
InputStream i = p.getInputStream();
StringBuilder sb = new StringBuilder();
for(  int c = 0 ; ( c =  i.read() ) > -1  ; ) {
    sb.append( ( char ) c );
}

Полная программа ниже.

import java.io.*;

public class Test { 
    public static void main ( String [] args ) throws IOException { 
        String result = execute( args[0] );
        System.out.println( result );
    }
    private static String execute( String command ) throws IOException  { 
        Process p = Runtime.getRuntime().exec( "cmd /c " + command );
        InputStream i = p.getInputStream();
        StringBuilder sb = new StringBuilder();
        for(  int c = 0 ; ( c =  i.read() ) > -1  ; ) {
            sb.append( ( char ) c );
        }
        i.close();
        return sb.toString();
    }
}

Образец ouput (использование команды типа)

C:\oreyes\samples\java\readinput>java Test "type hello.txt"
This is a sample file
with some
lines

Демонстрационный вывод (dir)

 C:\oreyes\samples\java\readinput>java Test "dir"
 El volumen de la unidad C no tiene etiqueta.
 El número de serie del volumen es:

 Directorio de C:\oreyes\samples\java\readinput

12/16/2008  05:51 PM    <DIR>          .
12/16/2008  05:51 PM    <DIR>          ..
12/16/2008  05:50 PM                42 hello.txt
12/16/2008  05:38 PM             1,209 Test.class
12/16/2008  05:47 PM               682 Test.java
               3 archivos          1,933 bytes
               2 dirs            840 bytes libres

Попытка любой

java Test netstat
java Test tasklist
java Test "taskkill /pid 416"

РЕДАКТИРОВАНИЕ

я должен признать, что я не на 100% уверен, что это - "лучший" способ сделать это. Не стесняйтесь отправлять ссылки и/или код, чтобы показать, как он может быть улучшен или что случилось с этим.

0
ответ дан 30 November 2019 в 15:01
поделиться

Значок/Незначок:

stream := open("ls", "p")
while line := read(stream) do { 
    # stuff
}

документы называют это каналом. Одна из хороших вещей - то, что это заставляет вывод быть похожим, Вы просто читаете файл. Это также означает, что можно записать в stdin приложения, если Вы должны.

2
ответ дан 30 November 2019 в 15:01
поделиться

Perl, иначе:

use IPC::Run3

my ($stdout, $stderr);
run3 ['ls'], undef, \$stdout, \$stderr
    or die "ls failed";

Полезный, потому что можно подать ввод команд и возвратить и stderr и stdout отдельно. Нигде рядом столь же аккуратный/страшный/медленный/тревожащий как IPC::Run, который может настроить каналы к подпрограммам.

2
ответ дан 30 November 2019 в 15:01
поделиться

J:

output=:2!:0'ls'
2
ответ дан 30 November 2019 в 15:01
поделиться

Почему нет все еще никакого c# парня здесь:)

Это - то, как сделать это в C#. Встроенный путь.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();

            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.FileName = "cmd";
            p.StartInfo.Arguments = "/c dir";
            p.Start();

            string res = p.StandardOutput.ReadToEnd();
            Console.WriteLine(res);
        }

    }
}
3
ответ дан 30 November 2019 в 15:01
поделиться

В C на Posix совместимые системы:

#include <stdio.h> 

FILE* stream = popen("/path/to/program", "rw");
fprintf(stream, "foo\n"); /* Use like you would a file stream. */
fclose(stream);
3
ответ дан 30 November 2019 в 15:01
поделиться

C (с glibc расширение):

#define _GNU_SOURCE
#include <stdio.h>
int main() {
    char *s = NULL;
    FILE *p = popen("ls", "r");
    getdelim(&s, NULL, '\0', p);
    pclose(p);
    printf("%s", s);
    return 0;
}

Хорошо, не действительно краткий или чистый. Это - жизнь в C...

3
ответ дан 30 November 2019 в 15:01
поделиться

В PHP

$output = `ls`;

или

$output = shell_exec('ls');
3
ответ дан 30 November 2019 в 15:01
поделиться

Еще один путь (или 2!) в Perl....

open my $pipe, 'ps |';
my @output = < $pipe >;
say @output;

открывают может также быть записан как так...

open my $pipe, '-|', 'ps'
4
ответ дан 30 November 2019 в 15:01
поделиться

Не забывайте Tcl:

set result [exec ls]
4
ответ дан 30 November 2019 в 15:01
поделиться

Несколько лет назад я записал плагин для jEdit, который взаимодействовал через интерфейс к исходному приложению. Это - то, что я раньше получал потоки от рабочего исполняемого файла. Только вещь, оставленная сделать, while((String s = stdout.readLine())!=null){...}:

/* File:    IOControl.java
 *
 * created: 10 July 2003
 * author:  dsm
 */
package org.jpop.io;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;

/**
 *  Controls the I/O for a process. When using the std[in|out|err] streams, they must all be put on
 *  different threads to avoid blocking!
 *
 * @author     dsm
 * @version    1.5
 */
public class IOControl extends Object {
    private Process process;
    private BufferedReader stdout;
    private BufferedReader stderr;
    private PrintStream stdin;

    /**
     *  Constructor for the IOControl object
     *
     * @param  process  The process to control I/O for
     */
    public IOControl(Process process) {
        this.process = process;
        this.stdin = new PrintStream(process.getOutputStream());
        this.stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
        this.stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    }

    /**
     *  Gets the stdin attribute of the IOControl object
     *
     * @return    The stdin value
     */
    public PrintStream getStdin() {
        return this.stdin;
    }

    /**
     *  Gets the stdout attribute of the IOControl object
     *
     * @return    The stdout value
     */
    public BufferedReader getStdout() {
        return this.stdout;
    }

    /**
     *  Gets the stderr attribute of the IOControl object
     *
     * @return    The stderr value
     */
    public BufferedReader getStderr() {
        return this.stderr;
    }

    /**
     *  Gets the process attribute of the IOControl object. To monitor the process (as opposed to
     *  just letting it run by itself) its necessary to create a thread like this: <pre>
     *. IOControl ioc;
     *.
     *. new Thread(){
     *.     public void run(){
     *.         while(true){    // only necessary if you want the process to respawn
     *.             try{
     *.                 ioc = new IOControl(Runtime.getRuntime().exec("procname"));
     *.                 // add some code to handle the IO streams
     *.                 ioc.getProcess().waitFor();
     *.             }catch(InterruptedException ie){
     *.                 // deal with exception
     *.             }catch(IOException ioe){
     *.                 // deal with exception
     *.             }
     *.
     *.             // a break condition can be included here to terminate the loop
     *.         }               // only necessary if you want the process to respawn
     *.     }
     *. }.start();
     *  </pre>
     *
     * @return    The process value
     */
    public Process getProcess() {
        return this.process;
    }
}
4
ответ дан 30 November 2019 в 15:01
поделиться

Mathematica:

output = Import["!foo", "Text"];
4
ответ дан 30 November 2019 в 15:01
поделиться

Ну, так как это системно-зависимо, существует много языков, которые не имеют встроенной обертки для различных системных вызовов необходимой.

, Например, сам язык Common LISP не был разработан для работы любой определенной системы. SBCL (Стальная реализация языка Common LISP Банков), тем не менее, обеспечивает расширение для подобных Unix систем, также, как и большинство других реализаций CL. Это является намного более "могущественным", чем просто получение вывода, конечно (Вы управляете рабочим процессом, может определить все виды направлений потока, и т.д., совещаться к руководству SBCL, главе 6.3), но легко записать немного макроса для этой определенной цели:

(defmacro with-input-from-command ((stream-name command args) &body body)
  "Binds the output stream of command to stream-name, then executes the body
   in an implicit progn."
  `(with-open-stream
       (,stream-name
         (sb-ext:process-output (sb-ext:run-program ,command
                                                    ,args
                                                    :search t
                                                    :output :stream)))
     ,@body))

Теперь, можно использовать его как это:

(with-input-from-command (ls "ls" '("-l"))
  ;;do fancy stuff with the ls stream
  )

, Возможно, Вы хотите хлебать все это в одну строку. Макрос тривиален (хотя, возможно, более краткий код возможен):

(defmacro syslurp (command args)
  "Returns the output from command as a string. command is to be supplied
   as string, args as a list of strings."
  (let ((istream (gensym))
        (ostream (gensym))
        (line (gensym)))
    `(with-input-from-command (,istream ,command ,args)
       (with-output-to-string (,ostream)
         (loop (let ((,line (read-line ,istream nil)))
                 (when (null ,line) (return))
                 (write-line ,line ,ostream)))))))

Теперь можно получить строку с этим вызовом:

(syslurp "ls" '("-l"))
6
ответ дан 30 November 2019 в 15:01
поделиться

Erlang:

os:cmd("ls")
6
ответ дан 30 November 2019 в 15:01
поделиться

В оболочке

OUTPUT=`ls`

или альтернативно

OUTPUT=$(ls)

Этот второй метод лучше, потому что это позволяет вложение, но не поддерживается всеми оболочками, в отличие от первого метода.

6
ответ дан 30 November 2019 в 15:01
поделиться

Haskell:

import Control.Exception
import System.IO
import System.Process
main = bracket (runInteractiveCommand "ls") close $ \(_, hOut, _, _) -> do
    output <- hGetContents hOut
    putStr output
  where close (hIn, hOut, hErr, pid) =
          mapM_ hClose [hIn, hOut, hErr] >> waitForProcess pid

С MissingH установил:

import System.Cmd.Utils
main = do
    (pid, output) <- pipeFrom "ls" []
    putStr output
    forceSuccess pid

Это - легкая операция на языках "связующего звена" как Perl и Ruby, но Haskell не.

7
ответ дан 30 November 2019 в 15:01
поделиться

Альтернативный метод в жемчуге

$output = qx/ls/;

Это имело преимущество, которое можно выбрать разделители, позволив использовать 'в команде (хотя, по моему скромному мнению, необходимо пересмотреть дизайн, если действительно необходимо сделать это). Другое важное преимущество состоит в том, что, если Вы используете одинарные кавычки в качестве разделителя, переменные не будут интерполированы (очень полезное)

7
ответ дан 30 November 2019 в 15:01
поделиться

Ruby: или обратные галочки или '%x' встроенный синтаксис.

puts `ls`;
puts %x{ls};
7
ответ дан 30 November 2019 в 15:01
поделиться

Еще один способ сделать это в Perl (TIMTOWTDI)

$output = <<`END`;
ls
END

Это специально полезно при встраивании относительно большого сценария оболочки в программу

Perl
8
ответ дан 30 November 2019 в 15:01
поделиться

[По требованию Alexman и dreeves - видит комментарии - Вы найдете в этом страница DZones Java Snippet полная версия независимый от OS для того, чтобы сделать, в этом экземпляре, 'ls'. Это - прямой ответ на их проблема кода .
то, Что следует ниже, является просто ядром: Runtime.exec, плюс 2 потока для слушания stdout и stderr.]

Java, "Простой!":

E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Executing cmd.exe /C dir *.java
...

Или в коде Java

String output = GoodWindowsExec.execute("dir");

, Но сделать это, необходимо кодировать...
... это является смущающим.

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
    InputStream is;
    String type;
    StringBuffer output = new StringBuffer();

    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }

    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);
                output.append(line+"\r\n")
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
    public String getOutput()
    {
        return this.output.toString();
    }
}
public class GoodWindowsExec
{
    public static void main(String args[])
    {
        if (args.length < 1)
        {
            System.out.println("USAGE: java GoodWindowsExec <cmd>");
            System.exit(1);
        }
    }
    public static String execute(String aCommand)
    {
        String output = "";
        try
        {            
            String osName = System.getProperty("os.name" );
            String[] cmd = new String[3];
            if( osName.equals( "Windows 95" ) )
            {
                cmd[0] = "command.com" ;
                cmd[1] = "/C" ;
                cmd[2] = aCommand;
            }
            else if( osName.startsWith( "Windows" ) )
            {
                cmd[0] = "cmd.exe" ;
                cmd[1] = "/C" ;
                cmd[2] = aCommand;
            }

            Runtime rt = Runtime.getRuntime();
            System.out.println("Executing " + cmd[0] + " " + cmd[1] 
                               + " " + cmd[2]);
            Process proc = rt.exec(cmd);
            // any error message?
            StreamGobbler errorGobbler = new 
                StreamGobbler(proc.getErrorStream(), "ERROR");            

            // any output?
            StreamGobbler outputGobbler = new 
                StreamGobbler(proc.getInputStream(), "OUTPUT");

            // kick them off
            errorGobbler.start();
            outputGobbler.start();

            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);   

            output = outputGobbler.getOutput();
            System.out.println("Final output: " + output);   

        } catch (Throwable t)
          {
            t.printStackTrace();
          }
        return output;
    }
}
9
ответ дан 30 November 2019 в 15:01
поделиться

Python:

import os
output = os.popen("foo").read()
12
ответ дан 30 November 2019 в 15:01
поделиться

C# 3.0, менее подробный, чем этот :

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        var info = new ProcessStartInfo("cmd", "/c dir") { UseShellExecute = false, RedirectStandardOutput = true };
        Console.WriteLine(Process.Start(info).StandardOutput.ReadToEnd());
    }
}

Протест: Производственный код должен правильно расположить объект Процесса...

4
ответ дан 30 November 2019 в 15:01
поделиться

Lua :

    foo = io.popen("ls"):read("*a")
3
ответ дан 30 November 2019 в 15:01
поделиться

Вот еще один способ Lisp:

(defun execute (program parameters &optional (buffer-size 1000))
  (let ((proc (sb-ext:run-program program parameters :search t :output :stream))
        (output (make-array buffer-size :adjustable t :fill-pointer t 
                            :element-type 'character)))
    (with-open-stream (stream (sb-ext:process-output proc))
      (setf (fill-pointer output) (read-sequence output stream)))
    output))

Затем, чтобы получить вашу строку:

(execute "cat" '("/etc/hosts"))

Если вы хотите запустить команду, которая выводит большой объем информации в STDOUT, вы можете запустить ее примерно так:

(execute "big-writer" '("some" "parameters") 1000000)

Последний параметр заранее выделяет большой объем места для вывода из big-writer. Я предполагаю, что эта функция может быть быстрее, чем чтение выходного потока по одной строке за раз.

3
ответ дан 30 November 2019 в 15:01
поделиться

Clozure Common Lisp:

(with-output-to-string (stream)
   (run-program "ls" '("-l") :output stream))

LispWorks

(with-output-to-string (*standard-output*)
  (sys:call-system-showing-output "ls -l" :prefix "" :show-cmd nil))
2
ответ дан 30 November 2019 в 15:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: