lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Lua built in os.execute() does not provide for separately catching the output, and the return value of a program being run.

In fact, doing so seems rather difficult. Here is a sample from Hamster sources (has some references to outside, but the approach should be cut-pastable):

(and I wouldn't mind having Lua provide that 'catch_int' parameter in the future...)

-- rc_int [,stdout_str, stderr_str]= Loc_Execute( cmd_str [,catch_int (1/2/3)=0] )
-- Note: On MSYS, 'os.execute' sees the _native_ Win32 file system whereas
--       'io.popen' sees the MSYS unix-like system (and commands).
local function Loc_Execute( cmd, catch )
    catch= catch or 0   -- nul mask
    local rc,sout,serr

    -- NetBSD has some problem (didn't get it fixed) with io.popen()
    if HOST_WIN32 or (BSD and BSD.netbsd) or (not USE_POPEN) then
        local tmp= Loc_TmpName()

        local tmp1= tmp.."1"
        local tmp2= tmp.."2"
local lookup= { [0]="", " > "..tmp1, " 2> "..tmp2, " 2> "..tmp2.." > "..tmp1 }

        rc= os.execute(cmd..lookup[catch])

        if catch==1 or catch==3 then
            sout= Loc_ReadAll(tmp1)
        if catch>=2 then
            serr= Loc_ReadAll(tmp2)

        ASSUME( USE_POPEN and (not HOST_WIN32) )
        local tmp_fn

        if catch>=2 then   -- no stderr
            tmp_fn= Loc_TmpName()
            cmd= cmd.." 2> "..tmp_fn

        -- We need some output to get the return code:
        local f= io.popen( cmd.." ; echo RC=$?" )
        ASSUME(f)  -- seems to be valid, even if cmd failed
        local str= f:read'*a'

        -- By searching at the very end of the string, we avoid clashes
        -- with whatever the command itself spit out.
        if str=="" then
-- Happened on OS X, with "sh: fork: Resource temporarily unavailable"
            -- error message. How to cope?
            rc= -99
local s1,s2= skip2( string.find( str, "(.*)RC=(%d+)%s* $" ) )
            rc= ASSUME( tonumber(s2) )

            if catch==1 or catch==3 then
                sout= s1
io.write(s1) -- os.execute() would have shown the output

        if tmp_fn then
            serr= Loc_ReadAll(tmp_fn)

-- Remove terminating newline (if any) from stdout: eases one- line analysis
    if sout then
sout= string.gsub( sout, "%s+$", "" ) -- remove any white space at the end

    --print( cmd, rc, sout, serr )
    return rc, sout,serr

luc1an0 kirjoitti 4.4.2007 kello 13:16:

David Given a écrit :
luc1an0 wrote:

My question can be very stupid, but I want to execute some shell commands with a pipe ( | ) like that :
os.execute(ps aux | grep my_program) or a generic way :
os.execute("my_command" "my_args" | another_command | ....)

I may be missing something here, but:

os.execute("ps aux | grep my_program")

...should work.

yes, works great... When i 've tried to do that, i had some bash errors. Probably due to an incorrect syntax...
And another simply question : How to don't return exit code if function even return string, for example
io.write(os.execute("pwd")) return this

I'm not sure what you're asking for here. Do you want to stop pwd printing it's output directly to the console and instead let Lua capture it as a
string? If so, use io.popen:

local f = io.popen("pwd") -- runs command
local l = f:read("*a") -- read output of command

Or did you mean something else?

Thanks !
"pwd" was just an example... In fact, if I execute command which return a status code (like "test"), I want to get it. But if the command return a string, I just want to get these string without the status code.

Thanks a lot :)