서브쉘

서브쉘

현재 netcat에 입력으로 파이프될 바이트를 생성하는 스크립트를 만들려고 합니다.

스크립트에 대한 아이디어는 다음과 같습니다.

(perl -e "print \"$BYTES\x00\";

cat file;

perl -e "print \"More bytes\"x16 . \"\r\n\"";) | netcat ip port

명령을 실행하기 위해 서브쉘과 명령 대체(예: $())를 사용해 보았습니다. 그런데 명령 대체를 사용할 때 스크립트 출력이 잘못된 이유를 이해할 수 없습니다. 여러 명령을 실행할 때 명령 대체가 출력을 잘못 파이프하는 것 같습니다. 왜 이런 일이 발생하는지 설명해 줄 수 있나요?

편집하다

다음은 명령 대체를 사용한 변형입니다.

$(perl -e "print \"$BYTES\x00\";

cat file;

perl -e "print \"More bytes\"x16 . \"\r\n\"";) | netcat ip port

답변1

자, 분석해 보겠습니다. 서브쉘은 체인으로 항목을 실행합니다(즉, 그룹화). 명령 체인을 (). 그러나 서브셸의 내용이 실행 시 함께 결합된다는 점을 제외하면 서브셸을 단일 명령인 것처럼 계속 사용할 수 있습니다. 즉, 서브셸은 여전히 ​​존재하므로 stdin서브 셸 안팎으로 파이프를 연결할 수 있습니다 stdout.stderr

반면에 명령 대체는 단순히 명령을 함께 연결하는 것과는 다릅니다. 대조적으로, 명령 대체는 변수 액세스와 약간 유사하지만 함수 호출을 사용합니다. 명령과 달리 변수에는 표준 파일 설명자가 없으므로 일반적으로 변수 안팎으로 어떤 것도 파이프할 수 없으며 명령 대체도 마찬가지입니다.

이를 더 명확하게 하기 위해, 아래에는 불분명할 수 있지만 정확할 수 있는 일련의 예와 이해하기 더 쉬울 수 있다고 생각되는 일련의 예가 있습니다.

date -u명령이 다음을 제공한다고 가정합니다 .

Thu Jul  2 13:42:27 UTC 2015

그러나 우리는 이 명령의 출력을 조작하려고 합니다. 그럼 이를 다음과 같이 파이프해 보겠습니다 sed.

user@host~> date -u | sed -e 's/ /    /g'
Thu    Jul        2    13:42:27    UTC    2015

와, 정말 흥미롭네요! 다음은 위와 완전히 동일합니다(셸의 ​​매뉴얼 페이지에서 읽을 수 있는 일부 환경적 차이점을 제외하고).

user@host~> (date -u) | sed -e 's/ /    /g'
Thu    Jul        2    13:42:27    UTC    2015

우리가 하는 일은 그룹뿐이므로 이는 놀라운 일이 아닙니다 date -u. 그러나 다음을 수행하면 처음에는 약간 이상해 보이는 결과가 나타납니다.

user@host~> $(date -u) | sed -e 's/ /    /g'
command not found: Thu

이는 출력을 $(date -u)정확하게 입력하는 것과 동일하기 때문입니다 . date -u따라서 위의 내용은 다음과 동일합니다.

user@host~> Thu Jul  2 13:42:27 UTC 2015 | sed -e 's/ /    /g'

물론 Thu이것은 명령이 아니기 때문에 오류가 발생합니다(적어도 제가 아는 바는 아닙니다). 확실히 아무것도 파이프하지 않습니다 stdout(그래서 sed어떤 입력도 얻지 못합니다).

그러나 명령 대체가 변수처럼 작동한다는 것을 알고 있으므로 변수 값을 다른 명령으로 파이프하는 방법을 알고 있으므로 이 문제를 쉽게 해결할 수 있습니다.

user@host~> echo $(date -u) | sed -e 's/ /    /g'
Thu    Jul        2    13:42:27    UTC    2015

하지만,Bash의 다른 변수와 마찬가지로, quote 명령으로 바꿔야 할 것입니다 "".

이제 더 간단한 예를 들어 다음을 고려하십시오.

user@host~> pwd
/home/hypothetical
user@host~> echo pwd
pwd
user@host~> echo "$(pwd)"
/home/hypothetical
user@host~> echo "$HOME"
/home/hypothetical
user@host~> echo (pwd)
error: your shell will tell you something weird that roughly means “Whoa! you tried to have me echo something that isn't text!”
user@host~> (pwd)
/home/hypothetical

이보다 더 간단하게 설명할 수 있는 방법은 없습니다. 명령 대체는 서브셸이 여전히 명령처럼 실행되는 변수 액세스처럼 작동합니다.

답변2

서브쉘

(command)command서브쉘에서 실행됩니다. 이는 여러 명령이 있는 경우 유용합니다.

  • (ls) | wc출력을 ls로 파이프할 것이므로 wc분명히 쓸 수 있습니다 ls | wc.
  • (ls ; date) | wclsdate합계 의 출력을 wc. 를 사용하면 에만 배관이 ls ; date | wc됩니다 .datewc

치환

$(command)실행되어 command출력으로 대체됩니다. 예를 들어

echo $(date)

$(date)로 대체되며 Thu Jul 2 15:20:43 CEST 2015결과는 다음과 같습니다.

echo Thu Jul  2 15:20:43 CEST 2015

둘을 합치다

두 가지를 결합할 수 있습니다.

file=/hello/word
( printf "%s has %d bytes\n" "${file}" $(wc -c < "$file") ; date ) | netcat ...

"$file"여기서는 또는 를 사용할 수 있습니다 "${file}".

파일 이름을 인용하는 것을 잊지 마십시오. 판타지 세계에서는 파일 이름이 일반 파일인 반면, 현실 세계에서는 파일 이름에 줄 바꿈, 공백, 쉼표, 탭 및 괄호가 포함되는 경우가 많습니다.

관련 정보