向屏幕发送命令:"stuff" 的限制,带有换行符的怪癖
Sending commands to screen: limits of "stuff", quirks w/ newlines
正在尝试通过“stuff”选项将长命令字符串传递给 Screen。当字符串很短且存在于 bash 中时,已在许多脚本中成功完成此操作,如下所示:
screen -d -m -S worker
screen -S worker -X -p 0 stuff $'/usr/bin/env python3 /root/worker.py\n'
在这种情况下,我正在从文件中读取命令。我可以将 '\n' 附加到该文件,但 $ () 构造函数会吃掉换行符。我已经尝试过 printf、ISF= 和许多排列组合,但在我可以保留换行符的地方,命令无法显示在屏幕上。
GEO_COMMAND=/foo/geo_command.txt
screen -S worker -X -p 0 stuff printf '%\n' "$GEO_COMMAND"
or
screen -S worker -X -p 0 stuff $GEO_COMMAND
GEO_COMMAND: ''foo -bar -geo1 -geo2 -blah -keys ..... 160 characters later ...; /root/finish_job.sh\n '
答案在下面突出显示,为后代添加:
screen 'stuff' 选项不喜欢大命令,对换行符非常讲究。
下面的评论/答案解决了可靠的换行问题,但要粘贴/执行大型命令,答案是使用 'readreg' 通过命令读取文本文件,然后使用第二个将其传递到屏幕使用 'paste' 命令,如下所示。
这种方法不需要尾随换行符,不需要用引号将命令(在文件中)括起来,并且也将接受导电命令 (; /foo/bar/sh)。
正如您已经发现的那样,$(cmd)
会从 cmd
的输出中删除尾随换行符,并且无法阻止此行为。
但是,您可以在 $()
之后使用追加尾随换行符。
screen -S worker -X -p 0 stuff "$(cat yourFile)"$'\n'
但是,这可能会出现意外行为,因为 screen stuff
会在将 ^C
和 \n
等控制序列输入您的会话之前对其进行解释。因此,假设文件名本身不包含任何特殊符号,获取脚本文件可能更明智:
screen -S worker -X -p 0 stuff '. yourFile\n'
screen
手册页建议 stuff
不应用于大字符串。作为替代方案,您可以将文件读入寄存器(一种缓冲区),然后将其粘贴。这里,p
是任意寄存器:
screen -S worker -X readreg p /foo/geo_command.txt
screen -S worker -X paste p
这种更直接的方法的优点是您不需要像 GEO_COMMAND="$(cat ...)"
那样通过中间 shell 变量,它会丢失最后的换行符。此外,数据不会被 screen
解释(例如,文件中的 2 个字符 \n
不会被 1 个字符的换行符替换)。
正在尝试通过“stuff”选项将长命令字符串传递给 Screen。当字符串很短且存在于 bash 中时,已在许多脚本中成功完成此操作,如下所示:
screen -d -m -S worker
screen -S worker -X -p 0 stuff $'/usr/bin/env python3 /root/worker.py\n'
在这种情况下,我正在从文件中读取命令。我可以将 '\n' 附加到该文件,但 $ () 构造函数会吃掉换行符。我已经尝试过 printf、ISF= 和许多排列组合,但在我可以保留换行符的地方,命令无法显示在屏幕上。
GEO_COMMAND=/foo/geo_command.txt
screen -S worker -X -p 0 stuff printf '%\n' "$GEO_COMMAND"
or
screen -S worker -X -p 0 stuff $GEO_COMMAND
GEO_COMMAND: ''foo -bar -geo1 -geo2 -blah -keys ..... 160 characters later ...; /root/finish_job.sh\n '
答案在下面突出显示,为后代添加:
screen 'stuff' 选项不喜欢大命令,对换行符非常讲究。
下面的评论/答案解决了可靠的换行问题,但要粘贴/执行大型命令,答案是使用 'readreg' 通过命令读取文本文件,然后使用第二个将其传递到屏幕使用 'paste' 命令,如下所示。
这种方法不需要尾随换行符,不需要用引号将命令(在文件中)括起来,并且也将接受导电命令 (; /foo/bar/sh)。
正如您已经发现的那样,$(cmd)
会从 cmd
的输出中删除尾随换行符,并且无法阻止此行为。
但是,您可以在 $()
之后使用追加尾随换行符。
screen -S worker -X -p 0 stuff "$(cat yourFile)"$'\n'
但是,这可能会出现意外行为,因为 screen stuff
会在将 ^C
和 \n
等控制序列输入您的会话之前对其进行解释。因此,假设文件名本身不包含任何特殊符号,获取脚本文件可能更明智:
screen -S worker -X -p 0 stuff '. yourFile\n'
screen
手册页建议 stuff
不应用于大字符串。作为替代方案,您可以将文件读入寄存器(一种缓冲区),然后将其粘贴。这里,p
是任意寄存器:
screen -S worker -X readreg p /foo/geo_command.txt
screen -S worker -X paste p
这种更直接的方法的优点是您不需要像 GEO_COMMAND="$(cat ...)"
那样通过中间 shell 变量,它会丢失最后的换行符。此外,数据不会被 screen
解释(例如,文件中的 2 个字符 \n
不会被 1 个字符的换行符替换)。