我需要在shell脚本中的tmux会话中使用bash -c
运行命令。与屏幕相比,tmux似乎需要引用整个命令,这会导致问题,因为bash -c
还需要引用正确的功能和更复杂的命令字符串。
在下面我试图用最小的例子来演示行为。我想要实现的目标涉及比ls
更复杂的命令。另外,为了我的目的,有必要扩展CMD
变量,因为它是在之前的脚本中构建的。
屏幕的最小脚本:
#!/bin/bash
set -x
CMD="ls -l; sleep 5"
screen -d -m bash -c "$CMD"
执行此脚本时,您会得到(stdout,因为-x
)
+ CMD='ls -l; sleep 5'
+ screen -d -m bash -c 'ls -l; sleep 5'
sleep命令用于有时间附加到屏幕会话,看看会发生什么。在执行上述脚本后附加到屏幕会话时,可以看到ls
命令的输出是长列表格式,即命令正确执行。
在tmux中,似乎必须引用命令才能在新会话中执行它。我使用以下脚本:
#!/bin/bash
set -x
CMD="ls -l; sleep 5"
tmux new -d "bash -c $CMD"
标准是
+ CMD='ls -l; sleep 5'
+ tmux new -d 'bash -c ls -l; sleep 5'
可以看出,bash -
c的cmd序列不再正确引用。当附加到创建的tmux会话时,可以看到,这导致ls
被执行而没有识别长列表选项。
我可以做些什么来传递给$CMD
的bash -c
字符串的正确引用(即扩展字符串周围的单引号)?
正如Eric Renouf建议的那样,逃离\"$CMD\"
产生
tmux new -d 'bash -c "ls -l; sleep 5"'
和'$CMD'
逃脱生产
tmux new -d 'bash -c '\''ls -l; sleep 5'\'''
两者都适用于提供的最小示例,但仍不完全是屏幕生成的,在我的情况下不起作用。
以下是我正在制作的确切电话(有关所有血腥细节,请参阅here):
$SCREEN -S "scalaris_$NODE_NAME" -d -m bash -x -f +B -c "$START_CMD; sleep 365d"
产生(-x
的输出)
/usr/bin/screen -S [email protected] -d -m bash -x -f +B -c '"/usr/bin/erl" -setcookie "chocolate chip cookie" -pa /home/jvf/code/scalaris/contrib/yaws/ebin -pa /home/jvf/code/scalaris/contrib/log4erl/ebin -pa /home/jvf/code/scalaris/ebin -sasl sasl_error_logger false -yaws embedded true -scalaris log_path "\"/home/jvf/code/scalaris/log/[email protected]\"" -scalaris docroot "\"/home/jvf/code/scalaris/docroot\"" -scalaris config "\"/home/jvf/code/scalaris/bin/scalaris.cfg\"" -scalaris local_config "\"/home/jvf/code/scalaris/bin/scalaris.local.cfg\"" -connect_all false -hidden -name [email protected] -scalaris start_type first -scalaris port 14195 -scalaris yaws_port 8000 -scalaris join_at_list '\''[0]'\'' -scalaris start_mgmt_server true -scalaris nodes_per_vm "1" -s scalaris +sbt db +swt low +sbwt short'
我认为到目前为止建议的解决方案不起作用,因为在命令中使用了双引号,但我并非100%肯定。如何使用tmux重现精确的引用屏幕(使用传递给bash -c
的完整命令的单引号)?
我相信你需要为tmux做这个,但为了获得你想要的额外报价,你可以在外部报价中逃脱它们,如:
tmux new -d "bash -c \"$CMD\""
或者你可以在大多数情况下把它们放在单引号中
tmux new -d "bash -c '$CMD'"
因为$ CMD将通过外部报价进行扩展