이 문서를 메모리로 동시에 읽는 것을 방지할 수 있는 쉘(있는 경우)은 무엇입니까?

이 문서를 메모리로 동시에 읽는 것을 방지할 수 있는 쉘(있는 경우)은 무엇입니까?

sh파일이 메모리에 맞지 않는 경우에도 실행될 수 있도록 거대한 자동 생성 쉘 스크립트를 작성하는 좋은 기술이 있습니까? 또한 쉘 자체가 heredoc을 메모리로 한꺼번에 읽지 않는다는 보장이 있습니까? 실제로 어떤 쉘이 이 문서를 메모리에 저장하지 않으며 sh이를 수행하기 위해 임의의 시스템의 일관성에 의존할 수 있습니까?

저는 GNU에 대해 읽고 shar있는데 너무 커서 메모리에 들어갈 수 없는 파일에 GNU를 사용할 수 있는지 궁금합니다. 콘텐츠를 저장하기 위해 heredocs를 사용합니다.

sed -e 's/^X//' << 'SHAR_EOF' | uudecode &&
Msome binary content
Xsome text content
SHAR_EOF

shar그러나 그러한 heredoc이 여러 개 있으며 스크립트의 일부가 실행되기 전에 구문 분석해야 할 수 있는 스크립트 끝에 일부 고정된 비heredoc 콘텐츠가 있습니다 . 쉘이 전체 스크립트를 구문 분석하지 않으면 첫 번째 명령을 실행하기 전에 잘못된 스크립트를 거부하는 것이 불가능합니다.

다음은 shar 아카이브의 후행 셸 주석 조각입니다.

...
else
test `LC_ALL=C wc -c < 'a.binary'` -ne 126472 && \
  ${echo} "restoration warning:  size of 'a.binary' is not 126472"
  fi
fi
if rm -fr ${lock_dir}
then ${echo} "x - removed lock directory ${lock_dir}."
else ${echo} "x - failed to remove lock directory ${lock_dir}."
     exit 1
fi
exit 0

답변1

쉘이 여기의 전체 문서를 메모리에 로드할 것인지 여부에 대한 보장은 없습니다. 거대한 스크립트는 흔하지 않으므로 쉘 구현자는 이 상황을 최적화할 가능성이 없습니다. 실행이 시작되기 전에 전체 스크립트를 메모리에 로드하지 않고 실행하는 것은 다소 바람직하지 않지만 모든 일반 쉘은 완전히 로드되기 전에 실행됩니다. 즉, 실행 중에 스크립트 파일이 수정되면 쓰레기가 됩니다.

실험적으로 Debian에서 jessie, dash, bash, mksh 및 zsh는 이 문서의 130kB를 메모리에 로드하는 반면 ksh93은 추가 메모리를 할당하지 않고 64kB 청크를 복사합니다. 따라서 메모리에 맞지 않는 여기서 문서를 사용하는 유일한 방법은 스크립트가 ksh93(또는 ksh88)을 사용하여 실행되는지 확인하는 것입니다. 이 작업을 수행하기 전에 다른 버전도 있는지 확인하십시오. 모든 것을 확인하지는 않았습니다. ksh 아직 버전은 동일하게 동작합니다.

이식성을 높이기 위해 할 수 있는 일은 모든 데이터를 스크립트 끝에 넣고 이를 사용하여 tail -c $offset페이로드를 추출하는 것입니다. 일반 쉘은 스크립트를 실행하기 전에 메모리에 스크립트를 완전히 로드하지 않기 때문에 실제로 작동합니다. 이 접근 방식의 장점은 페이로드가 바이너리일 수 있다는 것입니다. 이 문서는 heredoc 끝 문자열이나 null 바이트를 포함할 수 없습니다.

스크립트가 변경 불가능한 경우 페이로드 오프셋을 하드코딩할 수 있습니다. 그렇지 않은 경우 스크립트 끝에 구별 가능한 마커를 배치하고 awk를 사용하여 해당 위치를 확인할 수 있습니다.

offset=$(awk '{offset += length($0) + 1}
              $0 == "# payload starts here (do not remove this magic comment)" {
                  print offset; exit
              }')
tail -c "$offset" <"$0" — …
# payload starts here (do not remove this magic comment)

페이로드가 여러 개인 경우 이를 추출하려면 더 복잡한 명령이 필요합니다. head -c이는 모든 UNIX 변형에 존재하는 것은 아닙니다 . 이를 사용하여 dd ibs=1 count=$bytes동일한 효과를 얻을 수 있지만 많은 dd구현이 한 번에 1바이트를 복사하므로 속도가 매우 느릴 수 있습니다. tar 아카이브를 첨부하고 이름별로 파일을 추출하는 것이 좋습니다.

관련 정보