![서브쉘](https://linux55.com/image/68162/%EC%84%9C%EB%B8%8C%EC%89%98.png)
현재 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) | wc
ls
date
합계 의 출력을wc
. 를 사용하면 에만 배관이ls ; date | wc
됩니다 .date
wc
치환
$(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}"
.
파일 이름을 인용하는 것을 잊지 마십시오. 판타지 세계에서는 파일 이름이 일반 파일인 반면, 현실 세계에서는 파일 이름에 줄 바꿈, 공백, 쉼표, 탭 및 괄호가 포함되는 경우가 많습니다.