双向算子如何用于(g)awk?

时间:2019-05-27 14:08:35

标签: awk

我一直在研究awk中的双向运算符,并试图理解它。

https://www.gnu.org/software/gawk/manual/html_node/Two_002dway-I_002fO.html#Two_002dway-I_002fO

所以我在.awk文件中尝试过

BEGIN {
cmd="tr [a-z] [A-Z]"
print "hi" |& cmd
close(cmd,"to")
cmd |& getline
close(cmd)
}

在这里找到https://books.google.se/books?id=NrZTDwAAQBAJ&pg=PA322&lpg=PA322&dq=bidirectional+pipeline+awk+example&source=bl&ots=awgGmpZBxm&sig=ACfU3U0jxy2GO2qaUb-gCOrP9CmrC3SsYA&hl=sv&sa=X&ved=2ahUKEwijw8i267viAhXq-ioKHRyWDwMQ6AEwC3oECAgQAQ#v=onepage&q=bidirectional%20pipeline%20awk%20example&f=false

这看起来还不错,所以我尝试对其进行修改,

BEGIN {
cmd="ssh some_server"
print "ls /some/file" |& cmd
close(cmd,"to")
cmd |& getline
print $0
close(cmd)
}

这失败了。我设法登录并获得横幅。然后我得到消息,

  

警告:无法访问tty(错误文件描述符)。

随后程序终止。但是,“ ls”命令未运行。有谁知道我错过了什么?

编辑

我也尝试过

BEGIN {
cmd="ssh some_server"
print "ls /some/file" |& cmd
cmd |& getline
print $0
close(cmd)
}

,而不会在任一方向上关闭流。结果是不可预测的。它要么挂起,要么失败。至少不起作用。

虽然运行“ ssh服务器ls / some / file”工作正常,所以我怀疑它是abk管道,用于bash / tcsh问题。

EDIT2

这里还有很多其他建议,所以我认为我需要更新我的问题。有时,看来MVCE可能会引起更多问题,这可能会有所帮助...

无论如何,这个想法是启动一个ssh会话,我可以继续向该ssh会话发送新命令,直到完成操作为止,然后关闭ssh会话。因此,这个想法是启动一个ssh shell会话,然后通过管道将命令传递给它,并使用此运算符读取回复。

BEGIN {
cmd="ssh some_server"
print "ls /some/file" |& cmd
cmd |& getline
print $0
print "some other command" |& cmd
cmd |& getline
close(cmd)
}

此外,还有其他选项可以考虑,但没有一个选项会很容易。

EDIT3

我想在这里重新开始。

我想要做的是使用标准linux RHEL7发行版附带的ssh客户端启动ssh会话。然后,我想保持会话打开状态,同时继续向其发送命令。完成后,我需要终止会话。从bash看起来像这样,

ssh host
command1
command2
exit 

一个要求是,这是通过纯awk脚本完成的。所有其他选择只会在将来造成更多问题。注意用户名被忽略。目前,这已在我们的环境中处理,并且ssh 10.10.10.10可以正常运行。

BR 帕特里克

1 个答案:

答案 0 :(得分:0)

  1. 这不是您使用ssh执行远程命令的方式,ssh some_server -t 'command'是这样。
  2. 这不是您使用getline while ( (cmd |& getline line) > 0 )读取协同处理输出的方式。

尝试此操作,无需共同处理:

BEGIN {
    cmd = "ssh some_server \047ls /some/file\047"
    while ( (cmd | getline line) > 0 ) {
        print line
    }
    close(cmd)
}

尽管您确实希望使用协同进程,但是您需要ssh在远程计算机上创建一些进程,随后的命令可以通过该进程传递到该进程。也许会产生贝壳?过去我完全不参与awk,但在shell中使用

coproc ssh_conn { ssh -T ... some_tool_waiting_for_input }

创建一个远程进程和一个命名管道,并随后对其进行写入:

printf '%s\0' 'command' >&"${ssh_conn[1]}"

并读取其输出:

IFS= read -r -d '' resp <&"${ssh_conn[0]}".

因此,您需要弄清楚ssh -T ... some_tool_waiting_for_input是从awk进行此操作的起点(我认为这是一个坏主意,因为管理进程是shell的设计目标,而不是awk的设计目标-处理文字)。

在上述情况下,我的远程工具读取了以nul结尾的字符串,而不是以换行符结尾的字符串,因此我可以向其中发送多行文本。您的要求可能有所不同。

为了安全起见,我的远程命令要求本地命令对自身进行身份验证,并且不允许我的本地命令以外的任何其他设备进行连接,您可能需要考虑这样做,而不是生成一个远程外壳程序,然后任何人都可以连接到该外壳程序以执行命令您的远程计算机。

顺便说一句,请尝试在您的ssh命令中添加-T以摆脱Warning: no access to tty (Bad file descriptor)