awk 사이의 파이핑을 피하는 방법은 무엇입니까?

awk 사이의 파이핑을 피하는 방법은 무엇입니까?

나는 내 사용자의 에서 실행되는 다음 스크립트를 작성하여 crontabSSH 포트 전달을 구문 분석하고 ~/.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를 실행합니다.

관련 정보