JSA里的ffi(12)——Linux里执行脚本并获取输出
wils
创作者俱乐部成员
Linux版wps的Shell方法一直有问题,不能带参数执行脚本
之前分享过,使用glibc里的system方法,可以带参数,并等待脚本执行结束,是个好办法
但system方法不能获取脚本输出
现在有了ffi,正好试一下获取输出
function zz()
{
const {pipe, close, fork, execlp} = ffi.LoadLibrary("/usr/lib/musl/lib/libc.so", {
pipe: { returnType: "int32", parameters: ["pointer"]},
close: { returnType: "int32", parameters: ["int32"]},
fork: { returnType: "int32", parameters: []},
execlp: { returnType: "int32", parameters: ["string", "string", "string", "string", "pointer"]},
})
const fds = FFI.Malloc(8)
pipe(fds)
const rdFd = fds.Read('int32', 0)
const wtFd = fds.Read('int32', 4)
const pid = fork()
if (pid === 0) {
close(rdFd)
execlp('bash', 'bash', '-c', `echo -n 123 > /dev/fd/${wtFd}`, null)
}
close(wtFd)
console.log(FileSystem.ReadFile(`/dev/fd/${rdFd}`))
close(rdFd)
FFI.Free(fds)
}这里的so文件是安装了musl,如果你使用glibc,似乎需要在lib文件夹里弄个libc.so.6的别名,因为ffi现在好像不认.6结尾的文件名,有点尴尬
写的有点糙,没有对错误的处理等,但大概意思到了:
pipe创建管道
fork创建子进程,execlp执行脚本
脚本里写入管道
FileSystem.ReadFile读取管道
不得不说,Linux里的fork、pipe、sh真是令人愉快😁
完善一下写法,包装成一个函数,就可以方便的在Linux里执行各种脚本,获取输出的结果了
十分方便,比如yad弹个日期选择框,直接curl获取图片base64编码,直接执行py获取结果等,很多问题都简单了
后面又修改了一次
function tt()
{
const {pipe, close, dup2, fork, execlp, _exit, waitpid} = ffi.LoadLibrary("glibc.so", {
pipe: { returnType: "int32", parameters: ["pointer"]},
close: { returnType: "int32", parameters: ["int32"]},
dup2: { returnType: "int32", parameters: ["int32", "int32"]},
fork: { returnType: "int32", parameters: []},
execlp: { returnType: "int32", parameters: ["string", "string", "string", "string", "pointer"]},
_exit: { returnType: "void", parameters: ["int32"]},
waitpid: { returnType: "int32", parameters: ["int32", "pointer", "int32"]},
})
const Fds = ffi.Array('int32', 2)
const fds = new Fds()
if (pipe(fds) !== 0) throw new Error('pipe failed')
const rdFd = fds.get(0)
const wtFd = fds.get(1)
const pid = fork()
if (pid < 0) throw new Error('fork failed')
if (pid === 0) {
close(rdFd)
dup2(wtFd, 1)
close(wtFd)
execlp('bash', 'bash', '-c', `yad --calendar`, null)
_exit(127)
}
close(wtFd)
const ret = FileSystem.ReadFile(`/dev/fd/${rdFd}`)
close(rdFd)
waitpid(pid, null, 0)
console.log(ret.trim())
}
@金山办公
创作者俱乐部成员
创作者俱乐部成员
创作者俱乐部成员