
LuaTeXコードのバックエンドでいくつかのLuaを書いている間、私は次のことを見つけました:背景として、ここにLuaコードがあります。このバージョンは標準のLuaです。しかし、この関数が何をしているのかを理解するためにLuaを知る必要はありません。
標準出力とエラーをLuaとTeXに返す関数が必要です。
Luaにはこれを行うライブラリ関数がないので、私は自分で書く必要がありました。
このバージョンでは、標準出力をファイルに書き込み、標準エラーを標準出力にリダイレクトします。それからそれを読んで返します。特にきれいではありませんが、より良い選択肢は明らかではありません。
local function exec_cmd(command, stdout_message, stderr_message)
local filename=os.tmpname()
local cmd = string.format(command .. " 2>&1 1> %s", filename)
local pipe = io.popen(cmd)
local stderr = pipe:read("*all")
pipe:close()
local f = assert(io.open(filename, "r"))
local stdout = f:read("*all")
f:close()
os.remove (filename)
if stdout ~= nil and stdout ~= '' then
print(string.format(stdout_message, stdout))
end
if stderr ~= nil and stderr ~= '' then
error(string.format(stderr_message, stderr))
end
end
今日は、混乱した瞬間に上記command
の関数のパラメータとして次のようなコードを書きました。
"wkhtmltopdf searchpath(foo.html) foo.pdf"
上記のLua関数の観点から、次のようになります。
exec_cmd("wkhtmltopdf searchpath(foo.html) foo.pdf", "STDOUT FROM WKHTMLTOPDF is %s", "STDERR FROM WKHTMLTOPDF IS %s")
したがって、次のコマンドがシェルに渡されます。
wkhtmltopdf searchpath(foo.html) foo.pdf 2>&1 1> /tmp/lua_vyOiay
/tmp/lua_vyOiay
.
シェルに直接入力するとエラーが発生します(すでに解釈目的で使用されているLuaは忘れてください)。
bash:予期しない表示"("の近くに構文エラーがあります。
しかし、興味深いことに、このエラーは標準出力に渡されないようです。少なくとも上記のコマンドは収集せず、他の方法では収集できません。
Lua機能を安全に保つために、ここに質問があります。
- 上記の不可解なコマンドで何が起こっているのか、なぜエラーがstderrに送信されないのですか?これは参考用です。
- stderr文字列を収集してTeXプログラムを中断させるにはどうすればよいですか?
さらなる議論の後、2は少なくとも2つの方法で実施することができる。
2a. Bash シェル自体でこのエラーが発生しているようで、Bash シェル自体の標準エラーをキャプチャする方法が必要です。
2b。 Luaによって生成されたシェル標準エラーのLuaメソッドを取得します。
答え1
Luaプログラムはデフォルトで実行に帰結します。
io.popen("syntax(error) 2>&1 1>outputfile"):read("*all")
そのタスクは次のとおりです。
sh -c 'syntax(error) 2>&1 1>outputfile'
io.popen()
開始するシェルの標準出力をキャプチャしますが、標準エラーはキャプチャしません。構文エラーがない場合、リダイレクトは stderr をパイプに、stdout をファイルにディスパッチします。ただし、構文エラーのため、シェルはそこまで実行できないため、リダイレクトは処理されません。 (シェルはユーザーが指示する内容を理解していません。)
実際にstdoutとstderrをキャプチャするには、通常、外部コマンドを開始する前に両方ともパイプ(または他のもの)に接続します。たとえば、Pythonにはパラメータがsubprocess.Popen()
あります。しかし、Luaの標準ライブラリは少し荒れており、直接使用できないようです。この機能を提供するには、Cモジュールを作成する必要があります。stdout
stderr
説明で述べたように、コマンドをラップすると、eval
結果のコマンドラインが次のようになります。
eval 'syntax(error)' 2>&1 1>outputfile
シェルはそれを実行する前に方向の再指定を処理しますeval
。ただし、もちろん、コマンド内にある可能性のある単一引用符を保護するには、エスケープセットを追加する必要があります。