Interactive popen () Lua call

I am trying to create a program that launches a shell in the background and sends it commands to execute and returns a result. This is the code:

--note: this runs on windows but I assume replacing "cmd" with "sh" it can run on linux as well exe,err=io.popen("cmd > stdout.txt 2> stderr.txt"); if not exe then print("Could not run command. Error: "..err) return else print("Command run successfully... ready!") end stdout,err=io.open("stdout.txt","r") if not stdout then print("Could not open stdout: "..err) return end stderr,err=io.open("stderr.txt","r") if not stdout then print("Could not open stderr: "..err) return end function execute(str) exe:write(str) return stdout:read("*all") or stderr:read("*all") or "nil" end repeat print("COMMAND: ") userinput=io.read("*line") print("You entered: '"..userinput.."'") if userinput=="" then print "Empty line! Exiting program..." break end print("Result: "..execute(userinput)) until true print "Closing..." execute("exit") print "1" exe:close() print "2" stdout:close() print "3" stderr:close() print "Finished!" 

Problem: when you exit the program, it freezes when you call exe:close() . The execution loop behaves strangely too (sometimes I have to press the enter key several times for userinput=io.read("*line") .

I googled to see if the file works: close () also works with the file descriptor, which is the result of io.popen (), but did not find anything. But this challenge does not fail. He just hangs up. In other words, the output of the program is as follows:

 Command run successfully... ready! COMMAND: dir dir You entered: 'dirdir' Result: Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\lua> C:\lua> C:\lua> Closing... 1 
+4
source share
1 answer

Lua depends only on ANSI C functions. Therefore, io.popen uses the popen(3) function. Quote from this guide:

Since a channel is, by definition, unidirectional, a type argument can indicate only read or write, not both; the resulting stream is read-only or write-only, respectively.

You are trying to solve this restriction by redirecting the output to a file and at the same time open this file and read it after running the command. However, in this case, you may run into problems with output buffering - I think this is what you are experiencing.

Instead of trying to get around io.popen , you can try the Lua Ex API ( here is the wiki page ), which provides an alternative process that creates the API and allows you to do these things:

 -- popen2(), from http://lua-users.org/wiki/ExtensionProposal function popen2(...) local in_rd, in_wr = io.pipe() local out_rd, out_wr = io.pipe() local proc, err = os.spawn{stdin = in_rd, stdout = out_wr, ...} in_rd:close(); out_wr:close() if not proc then in_wr:close(); out_rd:close() return proc, err end return proc, out_rd, in_wr end -- usage: local p, i, o = assert(popen2("wc", "-w")) o:write("Hello world"); o:close() print(i:read"*l"); i:close() p:wait() 
+8
source

Source: https://habr.com/ru/post/1389122/


All Articles