When writing a lua script, I came across one thing: io.popen, judging by the documentation, cannot transfer the descriptors stdin and stdout of the process being started at the same time.

Example problem code:

cmdexecute = function(cmd, input) local f = io.popen(cmd, "w"); if tostring(input) ~= nil then f:write(tostring(input)); end; local l = f:read("*a"); f:close(); return (l); end; if cmdexecute('xargs ps', 'aux') ~= nil then print 'ps aux что-то выдал'; else print 'ps aux промолчал'; end; 

Result of performance:

 Длинный-длинный вывод ps aux... ps aux промолчал 

But it should be in theory:

 ps aux что-то выдал 

Question: how to get descriptors for both stdin and stdout from popen? Or perhaps there is some other solution to the problem, without io.popen ?

Upd: due to the relevance of the issue I explain: solutions with ffi valid .

  • and what, in fact, is the question? - aleksandr barakin
  • Clarified in question - val
  • Based on the answer, @Pavel has created a module: github.com/v1993/systemscripting . - val

2 answers 2

The lua-subprocess module should help you.

The subprocess.popen function takes the last argument of a table with named options. Among them are the options stdin , stdout and stderr , where you can pass a string (file name), number (system file descriptor), file object or a special constant subprocess.PIPE , which will create a pipe for this stream and store it in the returned object.

  • "... for this thread ..." Maybe, after all the process? - val
  • one
    @val apologize for the late reply - but still flow. This is a data stream (stream), not a control thread (thread). - Pavel Mayorov

io.popen gives the interface to the system posix function popen, yes, it can only work in one direction. In your case, writing something in ps is not necessary. If you open it for reading, it will certainly read. But as I understand it, ps for your example only ...

In POSIX, there is only 1 way to work with both file descriptors of the called process. Creating pairs of sockets, binding one of the ends of these connections to file descriptors 0 and 1 ( dup2 ). Then the fork is executed and the child process calls the desired program.

In Lua, judging by the documentation of such tools is not provided. So a direct answer to your question is to get both stdin and stdout at the same time impossible. From the solutions I see only redirection of the output of the program to the file and subsequent reading of this file. Or input for the program is written in advance to the file and served as input. And you can still experiment with named channels. mkfifo create a named channel in the file system, send it to the program or redirect from the program to it and open this channel in lua as a regular file and try to write / read.