Bash에게 이 오류를 표준 오류로 보내라고 지시하세요.

Bash에게 이 오류를 표준 오류로 보내라고 지시하세요.

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 기능을 안전하게 유지하기 위해 여기에 질문이 있습니다.

  1. 위의 말도 안되는 명령에 무슨 일이 일어나고 있으며 왜 오류가 stderr로 전송되지 않습니까? 이것은 단지 참고용입니다.
  2. 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 모듈을 작성해야 합니다.stdoutstderr

설명에서 언급했듯이 명령을 래핑하면 eval결과 명령줄이 다음과 같이 도움이 됩니다.

eval 'syntax(error)' 2>&1 1>outputfile

쉘은 이를 실행하기 전에 방향 재지정을 처리합니다 eval. 그러나 물론 명령 내에 있을 수 있는 작은따옴표를 보호하려면 추가 이스케이프 세트를 추가해야 합니다.

관련 정보