我有以下shell脚本。由于某种原因,java程序的标准错误和标准输出不会打印到文件“log”,而是始终显示在控制台中。是否存在某种类型或者我遗漏了什么?
JAVACMD="java -XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Xss128k -Xmx700m -jar program.jar >log 2>&1 "
echo "Starting server...";
$JAVACMD&
答案 0 :(得分:3)
令人遗憾的是,如果要将重定向运算符保留在字符串值中,则必须使用eval
。
与其他shell特殊字符一样,仅在未引用重定向运算符时对其进行评估。展开JAVACMD参数时,它将在空白上拆分,但不会重新评估它包含的任何特殊字符。使用eval
强制进行此重新评估。
eval
的问题是强制重新评估每个字符。在您的情况下,其他任何角色都不会有任何不良影响。如果您的字符串值包含一些其他shell特殊字符(例如;(){}
...),您不希望shell重新评估,则必须转义/引用它 in 字符串值所以eval
不会给它一个特殊的含义。
⋮
eval "$JAVACMD &"
为避免eval
出现问题,我建议将重定向移出字符串值:
JAVACMD="… program.jar"
⋮
$JAVACMD >log 2>&1 &
通过这种方式,您需要注意的字符串值中唯一的字符是空白字符(例如,如果您在其中一个选项/参数中需要一些嵌入的空格;如果您遇到此问题,您可能会考虑使用数组变量或"$@"
(所有类似Bourne的shell中可用的单数,类似数组的变量))。
答案 1 :(得分:2)
你试过了吗?
JAVACMD="java -XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Xss128k -Xmx700m -jar program.jar"
echo "Starting server...";
$JAVACMD >log 2>&1 &
重定向被视为java命令的参数,因为它们包含在变量中。
答案 2 :(得分:1)
你实际上不能将重定向粘贴在这样的变量中,并期望bash接受它们。简单的例子:
tesla:~ peter$ ECHOCMD='echo > log 2>&1'
tesla:~ peter$ $ECHOCMD
log 2>&1
即。你的重定向指标正在变成简单的参数,传递给你的java调用。
一种解决方法是说eval $JAVACMD
,但它不会让你的脚本更清洁。