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)
        end
        if catch>=2 then
            serr= Loc_ReadAll(tmp2)
        end

        os.remove(tmp1)
        os.remove(tmp2)
    else
        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
        end

        -- 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'
        f:close()

        -- 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
        else
local s1,s2= skip2( string.find( str, "(.*)RC=(%d+)%s* $" ) )
            rc= ASSUME( tonumber(s2) )

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

        if tmp_fn then
            serr= Loc_ReadAll(tmp_fn)
            os.remove(tmp_fn)
        end
    end

-- 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
    end

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



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
/home/fred
0


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
print(l)
f:close()

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 :)