zsh와 mksh는 어디에서 bash와 호환되지 않습니까?


11

다른 POSIX 호환 쉘이 어느 정도 bash를 대체 할 수 있습니까? 그것들은 진정한 "드롭 인 (drop-in)"대체 일 필요는 없지만, 대부분의 스크립트 로 작업 하고 나머지를 약간 수정하여 지원할 수있을 정도로 가깝습니다 .

  1. 초기화 스크립트, DHCP 클라이언트 스크립트 등의 명시 적 bash 스크립트를 최소한으로 수정하고 싶습니다.

  2. 더 전문적인 셸 스크립트 모음을 너무 많이 수정하지 않으려 고합니다.

  3. 문자열 조작 및 내장 정규식 패턴 일치와 같은 기능을 원합니다.

내가 아는 유일한 경쟁자는 zsh와 mksh입니다. 그래서 여기에 그들 중 하나 또는 둘 다에 좋은 사람들을 위해 :

  1. bash는 zsh와 mksh에 각각없는 기능은 무엇입니까?

  2. 쉘은 bash와 어떤 기능을 공유하지만 호환되지 않는 구문을 사용합니까?


3
명령 쉘의 비교 : ( en.wikipedia.org/wiki/Comparison_of_command_shells 배쉬 스크립팅에) 고급 가이드 : ( tldp.org/LDP/abs/html가 ) 수동 zsh을 ( zsh.sourceforge.net/Guide/zshguide.html ) MirBSD 쉘 매뉴얼 : ( mirbsd.org/htman/i386/man1/mksh.htm ). 죄송하지만이 질문은 너무 복잡합니다. 아마도 특정 Linux 배포판의 취약점을 해결하기 위해 bash를 패치하는 방법을 묻고 계십니까?
Tyler Maginnis

3
bashmksh와 zsh 를 대체 할 수있는 기능을 수행 할 수있는 쉘은 /bin/sh없습니다 bash.
llua

1
전체 쉘 쇼크 문제는 핵심 질문과 관련이없는 것으로 보이며 사람들을 산만하게합니다. 그래서 나는 그것을 제거했습니다
Michael Mrozek

3
전체 질문은 너무 광범위합니다. 아마도 당신은 그것을 제거해야합니다.
Tyler Maginnis

1
내가 실제로 가진 유일한 관심사는 BASH가 자유 소프트웨어 재단 (FSF)에 의해 잘 유지된다는 것입니다. 저의 연락처는 BASH 내에서 "기본 결함"의 계시가 더 강력하고 안전한 구현으로 이어질 것이라고 말합니다. 귀하의 요구 사항에 맞는 것을 추천하기 시작한 대체 쉘이 너무 많기 때문에 사용 사례에 대한 확실한 이해가 필요합니다. 그런 다음 O / S 측면에서 ... Bash에 묶인 너무 많은 것들이 결국 전체 O / S 호출을 BASH에 다시 쓰게됩니다. 내가 볼 수있는 가장 좋은 해결책은 alt-shell이 ​​유지되는 분포를 선택하는 것입니다.
Tyler Maginnis

답변:


19

스크립팅 기능을 고수하겠습니다. 풍부한 대화 형 기능 (명령 줄 버전, 완료, 프롬프트 등)은 매우 다른 경향이있어 완전히 호환되지 않는 방식으로 유사한 효과를 얻습니다. zsh의 어떤 기능이 bash에서 누락되었거나 그 반대입니까? 대화식 사용에 대한 몇 가지 지침을 제공합니다.

bash에 가장 가까운 것은 ATT ksh93 또는 mksh (Korn 쉘 및 복제본)입니다. Zsh에는 기능의 하위 세트가 있지만 zsh 기본 모드가 아닌 ksh 에뮬레이션 모드에서 실행해야합니다.

POSIX 기능 (현대 sh셸 에서 사용 가능 ), 상대적으로 모호한 기능 또는 대화식 사용을위한 위에서 언급 한 기능은 나열하지 않습니다 . 관찰은 데비안 wheezy에있는 bash 4.2, ksh 93u 및 mksh 40.9.20120630부터 유효합니다.

쉘 구문

인용

$'…'ksh93 및 mksh에서 백 슬래시 보간이 포함 된 리터럴 문자열을 사용할 수 있습니다. `$ "…"(번역 된 문자열)은 bash에 따라 다릅니다.

조건부 구성

Mksh 및 ksh93의는이 ;&A의를 통해 가을에 case문 있지만 ;;&이후의 경우를 테스트 할 수 있습니다. Mksh는이를 ;|위해 있으며 최근 mksh는 ;;&호환성을 허용 합니다.

((…))산술 표현식과 [[ … ]]테스트는 ksh 기능입니다. 일부 조건부 연산자는 다릅니다 (아래의 "조건부 표현식"참조).

코 프로세스

Ksh와 bash는 모두 공동 프로세스를 가지고 있지만 다르게 작동합니다.

기능

Mksh 및 ksh93 function name {…}은 표준 외에도 함수 정의에 대한 구문을 지원 name () {…}하지만 functionksh에서 범위 지정 규칙을 변경 name () …하면 호환성을 유지 해야 합니다. 함수 이름에서 허용되는 문자에 대한 규칙은 다양합니다. 영숫자 및 _.

버팀대 확장

Ksh93 및 mksh는 괄호 확장을 지원 {foo,bar}합니다. Ksh93은 숫자 범위를 지원 {1..42}하지만 mksh는 지원 하지 않습니다.

파라미터 확장

경우 ksh93 및 mksh 지원 문자열로 추출 ${VAR:offset}하고 ${VAR:offset:length}, 아닌 경우처럼 접는 ${VAR^}, ${VAR,}등 당신과 대소 문자 변환을 수행 할 수 있습니다 typeset -ltypeset -ubash는 ksh을 모두.

${VAR/PATTERN/STRING}또는로 대체 할 수 ${VAR/PATTERN//STRING}있습니다. STRING의 인용 규칙은 약간 다르므로 STRING에서 백 슬래시 (및 다른 문자)를 피하십시오 (변수를 작성하고 ${VAR/PATTERN/$REPLACEMENT}대체에 인용 문자가 포함 된 경우 대신 사용 ).

배열 확장 ( ${ARRAY[KEY]}, "${ARRAY[@]}", ${#ARRAY[@]}, ${!ARRAY[@]}KSH처럼 떠들썩한 파티에) 작동합니다.

${!VAR}is (간접 변수 참조) ${OTHERVAR}의 값 이 bash 특정 일 때 확장됩니다 (ksh는와 다른 일을 함 ). 이 이중 확장을 ksh로 가져 오려면 대신 이름 참조를 사용해야합니다 ( ). 동일하게 작동합니다.VAROTHERVAR${!VAR}typeset -n VAR=OTHERVAR; echo "$VAR"${!PREFIX*}

공정 대체

프로세스 대체 <(…)이며 >(…)ksh93에서는 지원되지만 mksh에서는 지원되지 않습니다.

와일드 카드 패턴

shopt -s extglobbash에서 활성화 해야하는 ksh 확장 글로브 패턴 은 항상 ksh93 및 mksh에서 사용 가능합니다.

Mksh는와 같은 문자 클래스를 지원하지 않습니다 [[:alpha:]].

IO 리디렉션

Bash와 ksh93은 의사 파일 과를 정의 하지만 mksh는 정의 하지 않습니다./dev/tcp/HOST/PORT/dev/udp/HOST/PORT

스크립트에서 리디렉션으로 와일드 카드를 확장 하면 (파일 이름이 패턴과 유일한 일치 var="*.txt"; echo hello >$a하는 a.txt경우 에 쓰는 것처럼) bash 관련 기능입니다 (다른 쉘은 스크립트에서 수행하지 않습니다).

<<< here-strings는 bash와 마찬가지로 ksh에서 작동합니다.

>&구문 오류를 리디렉션 하는 바로 가기 는 mksh에서도 지원되지만 ksh93에서는 지원되지 않습니다.

조건식

[[ … ]] 이중 괄호 구문

ksh의 이중 대괄호 구문은 bash에서와 같이 ATT ksh93 및 mksh에서 모두 지원됩니다.

파일 연산자

Ksh93, mksh 및 bash -a-e, -k(sticky), -G(egid가 소유 한), -O(euid가 소유 한 ), -ef(동일한 파일), -nt(보다 -ot오래된 ), ( 보다 오래된) 동의어를 포함하여 POSIX에 대한 동일한 확장을 지원합니다 .

-N FILE mksh는 (마지막 읽기 이후 수정)를 지원하지 않습니다.

Mksh에는 정규 표현식 일치 연산자가 없습니다 =~. Ksh93에는이 연산자가 있으며 bash에서와 동일한 일치를 수행하지만 BASH_REMATCH나중에 일치하는 그룹을 검색 하는 것과 동등한 기능은 없습니다 .

문자열 연산자

Ksh93 및 mksh는 동일한 문자열 비교 연산자 <>bash 및 ==동의어를 지원 =합니다. Mksh는 사전 설정 순서를 판별하기 위해 로케일 설정을 사용하지 않고 문자열을 바이트 문자열로 비교합니다.

다른 연산자

-v VAR변수가 정의되어 있는지 테스트하는 것은 bash마다 다릅니다. 모든 POSIX 셸에서을 사용할 수 있습니다 [ -z "${VAR+1}" ].

내장

alias

별명에서 허용되는 문자 세트는 모든 쉘에서 동일하지 않습니다. 기능과 동일하다고 생각합니다 (위 참조).

builtin

Ksh93에는이라는 내장 기능이 builtin있지만 내장 명령 으로 이름을 실행하지는 않습니다. command별명 및 기능을 무시하는 데 사용 합니다. 내장 명령이 있으면 내장 함수를 호출하고 그렇지 않으면 외부 명령을 사용합니다 (로 피할 수 있음 PATH= command error_out_if_this_is_not_a_builtin).

caller

이것은 bash 특정입니다. 당신과 비슷한 효과를 얻을 수 있습니다 .sh.fun, .sh.file그리고 .sh.lineno경우 ksh93있다. mksh에는 마침내 LINENO있습니다.

declare, local,typeset

declareksh에 대한 bash 특정 이름입니다 typeset. 사용 typeset: 그것은 또한 bash에서 작동합니다.

Mksh는 local에 대한 별칭으로 정의합니다 typeset. ksh93에서는 typeset별명 을 사용해야 합니다.

Mksh에는 연관 배열이 없습니다 (아직 출시되지 않은 버전으로 예정되어 있음).

typeset -tksh 에 bash (추적 기능) 와 정확히 동등한 것으로 생각하지 않습니다 .

cd

Ksh93에는 없습니다 -e.

echo

Ksh93 및 mksh 는 bash에서 -e-n같이 및 옵션을 처리합니다 . Mksh도 이해합니다 -E. ksh93 은이를 옵션으로 취급하지 않습니다. ksh93에서는 백 슬래시 확장이 기본적으로 꺼져 있고 mksh에서는 기본적으로 켜져 있습니다.

enable

Ksh는 내장 명령을 비활성화하는 방법을 제공하지 않습니다. 내장을 피하려면 외부 명령의 경로를 찾아 명시 ​​적으로 호출하십시오.

exec

Ksh93에는 -a있지만 없습니다 -l. MKSH도 없습니다.

export

ksh93도 mksh도 없습니다 export -n. 를 사용 typeset +x foo하는 대신, 그것은 떠들썩한 파티와 KSH에서 작동합니다.

Ksh는 환경을 통해 기능을 내 보내지 않습니다.

let

let bash와 ksh에서 동일합니다.

mapfile, readarray

이것은 bash 특정 기능입니다. while read루프 나 명령 대체를 사용 하여 파일을 읽고 여러 줄로 나눌 수 있습니다. 조심 IFS하고 낀다. 다음은 다음과 같습니다 mapfile -t lines </path/to/file.

IFS=$'\n'; set -f
lines=($(</path/to/file))
unset IFS; set +f

printf

printf매우 비슷합니다. ksh93은 모든 bash의 형식 지시문을 지원한다고 생각합니다. mksh는 지원하지 않습니다 %q또는 %(DATE_FORMAT)T; 일부 설치에서는 printfmksh 내장이 아니며 대신 외부 명령을 호출합니다.

printf -v VAR bash 특정이며, ksh는 항상 표준 출력으로 인쇄합니다.

read

readline에 대한 모든 옵션을 포함하여 몇 가지 옵션은 bash에 따라 다릅니다. 옵션은 -r, -d, -n, -N, -t, -ubash는, 경우 ksh93 및 mksh에서 동일하다.

readonly

동일한 구문을 사용하여 Ksh93 및 mksh에서 변수를 읽기 전용으로 선언 할 수 있습니다. 변수가 배열 인 경우 먼저 변수를 할당 한 다음을 사용하여 읽기 전용으로 만드십시오 readonly VAR. ksh에서는 함수를 읽기 전용으로 만들 수 없습니다.

set, shopt

모든에 옵션 setset -oPOSIX 또는 ksh 기능입니다.

shoptbash 특정입니다. 어쨌든 많은 옵션은 대화식 사용과 관련이 있습니다. 일부 옵션으로 사용 가능한 글 로빙 및 기타 기능에 대한 효과는 아래의 "옵션"섹션을 참조하십시오.

source

이 변형은 .ksh에도 존재합니다. bash 및 mksh에서, source이후의 현재 디렉토리를 검색 PATH하지만 ksh93에서는 정확히 ..

trap

DEBUG의사 신호 mksh에서 구현되지 않는다. ksh93에는 정보를보고하는 다른 방법이 있습니다. 자세한 내용은 설명서를 참조하십시오.

type

ksh에서 type의 별칭입니다 whence -v. mksh에서는 type -p실행 파일의 경로를 인쇄하지 않지만 사람이 읽을 수있는 메시지를 인쇄합니다. whence -p COMMAND대신 사용해야 합니다.

옵션

shopt -s dotglob — globbing에서 도트 파일을 무시하지 마십시오

dotglobksh93 의 옵션 을 에뮬레이트하기 위해을 설정할 수 있습니다 FIGNORE='@(.|..)'. mksh에는 이와 같은 것이 없다고 생각합니다.

shopt -s extglob — ksh 확장 글로브 패턴

extglob옵션은 항상 ksh에서 유효합니다.

shopt -s failglob — glob 패턴이 아무 것도 일치하지 않으면 오류

나는 이것이 mksh 또는 ksh93에 존재하지 않는다고 생각한다. zsh에서 수행됩니다 ( null_glob또는 csh_null_glob설정 하지 않은 경우 기본 동작 ).

shopt -s globstar—  **/재귀 globbing

Ksh93은을 (를 **/) 사용하여 재귀 적 globbing을 사용합니다 set -G. Mksh에는 재귀 적 globbing이 없습니다.

shopt -s lastpipe — 부모 쉘에서 파이프 라인의 마지막 명령을 실행

Ksh93은 항상 상위 쉘에서 파이프 라인의 마지막 명령을 실행하며, bash에서는 lastpipe옵션을 설정 해야합니다 . Mksh는 항상 서브 쉘에서 파이프 라인의 마지막 명령을 실행합니다.

shopt -s nocaseglob, shopt -s nocasematch- 대소 문자를 구분하지 않는 패턴

Mksh에는 대소 문자를 구분하지 않는 패턴 일치가 없습니다. Ksh93은 패턴별로 패턴을 지원 ~(i)합니다. 패턴 앞에 접두사를 붙입니다 .

shopt -s nullglob — 파일과 일치하지 않는 패턴을 빈 목록으로 확장

Mksh는 이것을 가지고 있지 않습니다. Ksh93은 패턴별로 패턴을 지원 ~(N)합니다. 패턴 앞에 접두사를 붙입니다 .

변수

분명히 대부분의 BASH_xxx변수는 ksh에 존재하지 않습니다. $BASHPID비용이 많이 들지만 휴대용으로 에뮬레이션 할 수 있으며 sh -c 'echo $PPID'최근 mksh에 추가되었습니다. BASH_LINE.sh.lineno경우 ksh93과 LINENOmksh에. BASH_SUBSHELL.sh.subshell경우 ksh93에서.

Mksh 및 ksh93은 ENV시작할 때 제공된 파일을 모두 소싱합니다 .

EUID그리고 UID경우 ksh93에 존재하지 않습니다. Mksh는 그들을 호출 USER_ID하고 KSH_UID; 이 없습니다 GROUPS.

FUNCNAMEFUNCNESTKSH에 존재하지 않습니다. Ksh93에는 .sh.fun및이 .sh.level있습니다. function foo { …; }괄호없이 선언 된 함수는에 고유 한 이름을 갖습니다 $0.

GLOBIGNOREksh93에 존재하지만 이름과 구문이 다릅니다.이라고 FIGNORE하며 콜론으로 구분 된 목록이 아닌 단일 패턴입니다. @(…|…)패턴을 사용하십시오 . Ksh FIGNORE는 완전히 다른 구문으로 bash를 사용합니다.

Ksh93 및 mksh에는 HOSTTYPE, MACHTYPE및 같은 것이 없습니다 OSTYPE. 도 아니다 SHELLOPTSTIMEFORMAT.

Mksh에는 PIPESTATUS이지만 ksh93에는 없습니다.

Mksh 및 ksh93에는 RANDOM.


문장의 시작 부분에 "등록되지 않은"상표 "mksh"를 정확하게 재생하지 않으려면 ( ""dd. ""대 ""dd ""참조 ) 여기에 "MirBSD"를 작성 하십시오. Korn Shell”대신에. "mksh"문자를 대문자로 표기하는 것은 항상 잘못된 것 입니다. 감사.
mirabilos

어떻게 $BASHPID에뮬레이션 할 수 sh -c 'echo $PPID'있습니까? (sh -c 'echo $PPID')Bash에서 시도 했지만와 같은 PID를 제공 $$합니다.
Franklin Yu

나는 그 질문이 여기 에 더 잘 맞는다고 생각한다 . 나는 거기에 질문을 복사했다.
Franklin Yu

4

이 질문은 너무 광범위합니다.

mkshzsh을은 많은 지원 포탄입니다 GNU bash는 - 특정 확장자를하지만 항상 이해되지 않는 몇 가지가 있습니다.

zsh는 더 많은 것을 지원하지만 POSIX 쉘 (GNU bash, AT & T ksh93 , mksh 등) 과 호환되지 않는 기본 zsh 모드에서만 지원합니다 . 또한 mksh는 훨씬 더 빠르며 빠르며 이식성이 뛰어납니다.

일반적으로 이것이 우리가 이야기하고있는 스크립트라면 테스트 해보십시오 . (mksh는 bash4 스타일 연관 배열을 아직 지원하지 않습니다. "declare"명령은 bash 고유의 "typeset"과 동일합니다. zsh에 대해 잘 알고 있지는 않습니다. ksh93에는 "local"이 없습니다. 그러나 "typeset"도 사용합니다.) 만약 이것이 bash-less 데비안 시스템을 실행하고 있다면 잊어 버리십시오. bash의 존재는“약속”(시스템의 API / ABI)의 일부이며 그에 많이 의존합니다.

면책 조항 : 저는 mksh 개발자입니다.


1

껍질의 ZSH 비교

그러나 최근 몇 년 동안 확장 프로그램에서 어느 정도의 크로스 오버가 발생했습니다. Zsh (3.1.6 현재)에는 bash의 ${var/old/new}' feature for replacing the text old with the text new in the parameter $var. Note one difference here: while both shells implement the syntax$ {var / # old / new} '및 ${var/%old/new}' for anchoring the match of old to the start or end of the parameter text, respectively, in zsh you can't put the#'또는 %' inside a parameter: in other words{var / $ old / new} '가 있으며 여기서 old는 #' treats that as an ordinary character in zsh, unlike bash. To do this sort of thing in zsh you can use (from 3.1.7) the new syntax for anchors in any pattern,(#s)'로 시작하여 문자열의 시작과 일치합니다 그리고`(#e) '는 끝과 일치합니다. EXTENDED_GLOB 옵션을 설정해야합니다.

나는 mksh에 가장 익숙하지 않으므로 그 대답을 어디에서 찾을 지 모르겠다.

쉘을 안전하게 대체하려는 경우, 논의중인 고유의 결함에 이르기까지 이러한 쉘 중 어느 것도 Bash와 크게 다르지 않습니다.

Perl과 같은 언어는 입력을보다 안전하게 처리합니다. 그러나 유지 관리 성 또한 중요합니다. Perl 쉘 교체는 잘 채택되지 않았습니다. 입력을 안전하게 처리하는 것은 쉘 관리자의 책임입니다. 따라서 스크립트를 작성할 때 모든 것을 검증하고, 검증하고, 검증하십시오! 코드 계약을 사용하여 항상 올바른 결과를 얻으십시오!

펄 쉘

쉘 충격에 대한 FSF 선언


실제로 다른 쉘에 동일한 결함이있는 경우-내가 본 토론에 따라 다소 의심 스럽습니다. 많은 타사 프로그램이 변수를 쉘없이 변수에 전달하기 때문에 문제입니다 검증 또는 무엇이든. 그렇다면 POSIX를 완전히 버릴 수도 있습니다.
DanL4096

1
Bash 프로젝트는 10 년 동안 0 일 동안 악용되었습니다. Microsoft Windows는 매주 0 일 동안 10 가지 이상의 익스플로잇을가집니다. 얼마나 많은 사람들이 이것에 대해 Bash 개발 팀을 괴롭 혔는지 아십니까? 그냥 업데이트하고 계속 진행하십시오! 별거 아니야.
Tyler Maginnis

1
@ DanL4096. 변수에 대해 충분한 온 전성 검사를 수행하지 않는 변수를 쉘 스크립트에 전달하면 POSIX를 폐기 할 이유가 없습니다. 문제는 우선 쉘 스크립트를 작성한 사람에게 있습니다.
fpmurphy 2016 년

0

기본적으로 활성화되어 있지 않은 기능 중 하나 mksh는 셸 기록입니다.

  • 당신에 .mkshrc불과 세트 :

    export HISTFILE=~/.mksh-history

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.