如何避免 awk 之间的管道传输?

如何避免 awk 之间的管道传输?

我编写了以下脚本,该脚本从我的用户的 运行crontab,解析SSH 端口转发,并在该行以“远程”、“本地”或“动态”结尾~/.ssh/config时自动连接它们。Host

示例~/.ssh/config块:

Host localsocksdynamic
     DynamicForward 8080
     Hostname 1.2.3.4

Host localwebserverremote
     RemoteForward *:8080 localhost:80
     Hostname 1.2.3.4

Host indirectaccesslocal
     LocalForward 2222 2.3.4.5:80
     Hostname 1.2.3.4

脚本:

#!/bin/sh

port_forwards=$(awk '/Host .*(remote|local|dynamic)/{printf $2} " "}' ~/.ssh/config  
for forward in ${port_forwards}
do
     port=$(awk "/${forward}/{f=1;next}/Host /{f=0}f" ~/.ssh/config | awk '/(Remote|Local|Dynamic)Forward/{print $2}' | cut -d':' -f2)
     [ -z ${port} ] || nc -z 127.0.0.1 ${port} || ssh -fqN ${forward} > /dev/null 2>&1
done

它工作正常,但我想知道是否可以组合行awk中的命令port=,以便不需要将一个命令通过管道传输awk到另一个命令。经过几个小时的尝试并尝试理解语法之后,我只是无法理解它。

我知道autossh存在并且是一种更好的方法来完成我正在做的事情,但这是一种学习经验,并尝试在不安装软件包的情况下完成相同的任务。

答案1

您可以通过一次 AWK 调用执行所有文本处理,这很简单,因为您只关心转发:

#!/bin/sh

awk '/^Host / { host = $2 } host && /(Remote|Local|Dynamic)Forward/ { port=$2; gsub(".*:", "", port); print host, port }' ~/.ssh/config | while read host port; do
    nc -z 127.0.0.1 "${port}" || ssh -fqN "${host}" > /dev/null 2>&1
done

AWK 脚本写得更清晰:

/^Host / { host = $2 }

host && /(Remote|Local|Dynamic)Forward/ {
    port=$2; gsub(".*:", "", port); print host, port
}

每当它看到“Host”语句时,它就会存储主机,然后在定义有效主机时遇到的行上,并匹配接受的“Forward”语句之一,检索目标端口,删除冒号之前的部分(如果有),然后输出主机和端口:

localsocksdynamic 8080
localwebserverremote 8080
indirectaccesslocal 2222

然后将其输入while read循环以检查端口并运行 SSH。

相关内容