현재 작업중인 쉘을 어떻게 확인할 수 있습니까?
ps명령 의 출력 만으로도 충분합니까?
유닉스의 다른 풍미에서 어떻게 이것을 할 수 있습니까?
현재 작업중인 쉘을 어떻게 확인할 수 있습니까?
ps명령 의 출력 만으로도 충분합니까?
유닉스의 다른 풍미에서 어떻게 이것을 할 수 있습니까?
답변:
현재 쉘의 실행 파일 이름 을 찾는 방법에는 세 가지가 있습니다 .
쉘의 실행 파일이 인 경우 세 가지 접근 방식을 모두 속일 수 /bin/sh있지만 실제로는 이름이 바뀝니다 bash(예 : 자주 발생).
따라서 ps출력이 수행 될지 여부에 대한 두 번째 질문은 " 항상 "이 아닙니다 .
echo $0 -쉘의 경우 실제 쉘인 프로그램 이름을 인쇄합니다.
ps -ef | grep $$ | grep -v grep-실행중인 프로세스 목록에서 현재 프로세스 ID를 찾습니다. 현재 프로세스는 쉘이므로 포함됩니다.
목록에 쉘의 프로세스 ID와 동일한 번호를 포함하는 다른 프로세스 가있을 수 있으므로 ps, 특히 해당 ID가 작은 경우 (예 : 쉘의 PID가 "5"인 경우) 동일한 grep출력 에서 "java5"또는 "perl5" !). 이것은 쉘 이름에 의존 할 수 없다는 점에서 "ps"접근 방식의 두 번째 문제입니다.
echo $SHELL-현재 쉘의 경로는 쉘의 SHELL변수 로 저장됩니다 . 이것에 대한주의 사항은 쉘을 서브 프로세스로 명시 적으로 시작하면 (예를 들어, 로그인 쉘이 아닌 경우) 로그인 쉘의 값을 대신 얻는다는 것입니다. 그럴 가능성이 있으면 ps또는 $0접근법을 사용하십시오 .
그러나 실행 파일이 실제 쉘과 일치하지 않으면 (예 : /bin/sh실제로 bash 또는 ksh) 휴리스틱이 필요합니다. 다양한 쉘에 특정한 환경 변수는 다음과 같습니다.
$version tcsh에 설정되어 있습니다
$BASH bash에 설정되어 있습니다.
$shell (소문자)는 csh 또는 tcsh에서 실제 쉘 이름으로 설정됩니다.
$ZSH_NAME zsh에 설정되어 있습니다
KSH가 보유 $PS3하고 $PS4설정된 정상 반면 본 셸 ( sh)만을 보유 $PS1하고 $PS2세트. 이것은 일반적으로 보인다 가장 어려운 구별하기 - 단지 사이에 환경 변수의 전체 세트의 차이 sh와 ksh우리는 솔라리스 회양목에 설치 한이다 $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS,와 $TMOUT.
echo ${.sh.version}반환 "나쁜 대체". 위의 내 솔루션보기
ps -ef | grep …………처럼 100 % 신뢰할 수는 없습니다.” 간단한 정규 표현식을 사용 egrep하거나 grep -e모든 의도와 목적에 100 %까지 쉽게 신뢰성을 가져올 수 있습니다 ps -ef | egrep "^\s*\d+\s+$$\s+". ^차종 확실히 우리가 줄의 처음부터 시작하고는 \d+먹는 UID 최대의는 $$PID를 일치하고 \s*및 \s+계정 및 대한 것은 다른 부분 사이의 공백을 보장합니다.
ps -ef | awk '$2==pid' pid=$$
ps -p $$
는 POSIX 옵션을 지원하는 유닉스 변형 ps -ef과 관련된 솔루션과 다른 솔루션에서 작동해야 grep하며 다른 곳에 나타날 수있는 일련의 자릿수를 grepping하여 오 탐지로 인해 발생하지 않습니다.ps
ps이해할 -p수 없으므로 사용해야 할 수도 있습니다 /bin/ps -p $$.
$$것을 제외하고 이해 fish합니다 ps -p %self.
/bin/ps. ps에 쉽게 설치할 수 있습니다 (실제로는 현재는 꽤 정상입니다) /usr/bin. $(which ps) -p $$더 나은 방법입니다. 물론 이것은 물고기와 다른 껍질에서는 작동하지 않습니다. 나는 그것이 (which ps) -p %self물고기에 있다고 생각합니다 .
readlink /proc/$$/exe
sh의해 에뮬레이트되는 bash경우 ps -p는 다음 /usr/bin/bash과 같이 실행하더라도sh
시험
ps -p $$ -oargs=
또는
ps -p $$ -ocomm=
ps -o fname --no-headers $$.
test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash. (내 스크립트의 다음 줄은 csh와 동일합니다.)
-q대신에 사용 합니다 -p.SHELL=$(ps -ocomm= -q $$)
사용자가 Bash를 사용하여 스크립트를 호출하고 있는지 확인하려면 다음을 수행하십시오.
if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
#!/bin/bash: if [ ! -n "$BASH" ] ;then exec bash $0; fi. 이 행을 사용하면 ksh 또는 sh를 사용하여 시작한 경우에도 bash를 사용하여 스크립트가 실행됩니다. 내 유스 케이스에는 명령 줄 인수가 필요하지 않지만 필요한 경우 추가 할 수 있습니다 $0.
당신은 시도 할 수 있습니다:
ps | grep `echo $$` | awk '{ print $4 }'
또는:
echo $SHELL
/pattern/ { action }를합니까?
$SHELL환경 변수에는 현재 사용자의 기본값으로 구성된 셸이 포함되어 있습니다. 현재 실행중인 쉘을 반영하지 않습니다. 또한 ps -p $$오 탐지 때문에 $$를 grepping 하는 것보다 사용하는 것이 좋습니다 .
awk,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
다음은 항상 사용 된 실제 쉘을 줄 것이다 - 그것은 실제 실행 파일의 이름이 아닌 쉘 이름 (예 얻는 ksh93대신 ksh, 등). 의 경우 /bin/sh, 실제 사용 된 쉘을 보여줍니다 dash.
ls -l /proc/$$/exe | sed 's%.*/%%'
나는 ls출력을 처리해서는 안된다고 말하는 많은 사람들이 있지만, 당신이 사용할 쉘을 특수 문자로 명명하거나 특수 문자로 명명 된 디렉토리에 배치 할 확률은 얼마입니까? 이 경우에도 여전히 다른 방식으로 수행하는 다른 예가 많이 있습니다.
Toby Speight가 지적한 것처럼 , 이것은 더 적절하고 깔끔한 방법으로 달성 할 수 있습니다.
basename $(readlink /proc/$$/exe)
/proc. 모든 세계가 리눅스 박스는 아닙니다.
basename $(readlink /proc/$$/exe)에 ls+ sed+ echo.
ash -> /bin/busybox
나는 많은 다른 접근법을 시도했으며 가장 좋은 방법은 다음과 같습니다.
ps -p $$
Cygwin 에서도 작동 하며 PID grepping으로 오 탐지를 생성 할 수 없습니다. 약간의 청소를 통해 실행 가능한 이름 만 출력합니다 (Cygwin 아래 경로가 있음).
ps -p $$ | tail -1 | awk '{print $NF}'
기억하지 않아도되는 함수를 만들 수 있습니다.
# Print currently active shell
shell () {
ps -p $$ | tail -1 | awk '{print $NF}'
}
... 그리고 그냥 실행하십시오 shell.
데비안과 Cygwin에서 테스트되었습니다.
ps, tail및 의 Windows 포트가 있더라도 gawkcmd는 $$PID로 정의하지 않으므로 일반 cmd에서는 확실히 작동하지 않습니다.
ps -p$$ -o comm=않습니까? POSIX는 모든 헤더를 비우면 헤더를 완전히 억제한다고 말합니다. ps직접 실행 된 스크립트 (예 :)로 소스를 제공 할 때 여전히 모든 답변 과 마찬가지로 실패 #!/bin/sh합니다.
부모 프로세스 인쇄에 대한 나의 변형 :
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
AWK가 대신 할 수있을 때 불필요한 응용 프로그램을 실행하지 마십시오.
awk, 때 ps -p "$$" -o 'comm='당신을 위해 그것을 할 수 있습니까?
쉘과 해당 버전을 찾는 방법에는 여러 가지가 있습니다. 나를 위해 일한 몇 가지가 있습니다.
똑바로
해시 접근
$> ******* (임의의 문자 세트를 입력하면 출력에 쉘 이름이 표시됩니다. 제 경우에는 -bash : chapter2-a-sample-isomorphic-app : command not found )
당신이 제공 /bin/sh지원 POSIX 표준과 시스템이 가지고 lsof에 대한 가능한 대안 - 설치 명령 lsof이 경우 수 수 pid2path- 당신은 또한 사용 (또는 적용) 할 수 인쇄 전체 경로가 다음 스크립트를 :
#!/bin/sh
# cat /usr/local/bin/cursh
set -eu
pid="$$"
set -- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login
unset echo env sed ps lsof awk getconf
# getconf _POSIX_VERSION # reliable test for availability of POSIX system?
PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`"
[ $? -ne 0 ] && { echo "'getconf PATH' failed"; exit 1; }
export PATH
cmd="lsof"
env -i PATH="${PATH}" type "$cmd" 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }
awkstr="`echo "$@" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`"
ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`"
[ "${ppid}"X = ""X ] && { echo "no ppid found"; exit 1; }
lsofstr="`lsof -p $ppid`" ||
{ printf "%s\n" "lsof failed" "try: sudo lsof -p \`ps -p \$\$ -o ppid=\`"; exit 1; }
printf "%s\n" "${lsofstr}" |
LC_ALL=C awk -v var="${awkstr}" '$NF ~ var {print $NF}'
-i(-> 환경 무시) 옵션 이 사용 가능한지 env확인하는 줄에 있기 때문에 bash에서 실패 lsof합니다. 실패 : env -i PATH="${PATH}" type lsof->env: ‘type’: No such file or directory
Bash (특정 버전)를 실행하고 있는지 확인하려면 $BASH_VERSINFO배열 변수 를 사용하는 것이 가장 좋습니다 . (읽기 전용) 배열 변수는 환경에서 설정할 수 없으므로 현재 셸에서 오는지 확인할 수 있습니다.
그러나 Bash는로 호출 될 때 다른 동작 sh을하기 때문에 $BASH환경 변수가로 끝나는지도 확인해야합니다 /bash.
내가 -밑줄이 아닌 함수 이름을 사용 하고 연관 배열 (Bash 4에 추가)에 의존 하는 스크립트 에서 다음과 같은 위생 검사 (유용한 사용자 오류 메시지 포함)가 있습니다.
case `eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null` in
*/bash@[456789])
# Claims bash version 4+, check for func-names and associative arrays
if ! eval "declare -A _ARRAY && func-name() { :; }" 2>/dev/null; then
echo >&2 "bash $BASH_VERSION is not supported (not really bash?)"
exit 1
fi
;;
*/bash@[123])
echo >&2 "bash $BASH_VERSION is not supported (version 4+ required)"
exit 1
;;
*)
echo >&2 "This script requires BASH (version 4+) - not regular sh"
echo >&2 "Re-run as \"bash $CMD\" for proper operation"
exit 1
;;
esac
첫 번째 경우 기능에 대한 편집증 기능 검사를 생략하고 향후 Bash 버전이 호환 될 것이라고 가정 할 수 있습니다.
fish쉘에 대한 답변 이 없습니다 (변수가 $$없거나 $0).
(에 테스트 나를 위해이 작품을 sh, bash, fish, ksh, csh, true, tcsh,과 zsh, 오픈 수세 13.2) :
ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'
이 명령은과 같은 문자열을 출력합니다 bash. 여기에만 사용하고 ps, tail그리고 sed(GNU의 extesions하지 않고, 추가하려고 --posix그것을 확인). 그것들은 모두 표준 POSIX 명령입니다. 나는 확실 tail하게 제거 할 수 있지만 나의 sedfu는 이것을하기에 충분히 강하지 않다.
이 솔루션은 OS X에서 작동하지 않으므로 이식성이 좋지 않습니다. :(
sed: invalid option -- 'E'bash 3.2.51과 tcsh 6.15.00을 얻는다
내 해결책 :
ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1
다른 플랫폼과 셸에서 이식 가능해야합니다. 그것은 사용하는 ps다른 솔루션처럼, 그러나 그것은에 의존하지 않는 sed또는 awk및 필터 배관에서 정크 밖으로 ps자체가 너무 쉘은 항상 마지막 항목이되어야한다고. 이렇게하면 이식 불가능한 PID 변수에 의존하거나 올바른 행과 열을 선택할 필요가 없습니다.
Bash, Z shell ( zsh) 및 fish (다른 PID 변수를 사용하기 때문에 물고기에 대한 표현을 변경하지 않고는 대부분의 솔루션에서 작동하지 않음 )를 사용하여 Debian 및 macOS에서 테스트 했습니다.
echo $$ # Gives the Parent Process ID
ps -ef | grep $$ | awk '{print $8}' # Use the PID to see what the process is.
grep $$것은 신뢰할 수 없습니다. ps -ef | awk -v pid=$$ '$2==pid { print $8 }'더 낫지 만 왜 사용하지 ps -p $$않습니까?
Mac OS X (및 FreeBSD) :
ps -p $$ -axco command | sed -n '$p'
zsh하고, 그것은 나에게 주었다 -bash.
mutt... : -b
"ps"출력에서 PID를 제거하는 것은 필요하지 않습니다. / proc 디렉토리 구조에서 PID에 대한 각 명령 행을 읽을 수 있기 때문입니다.
echo $(cat /proc/$$/cmdline)
그러나 그것은 단순히 다음보다 더 나을 수는 없습니다.
echo $0
이름이 나타내는 것과 실제로 다른 쉘을 실행하는 경우 한 가지 아이디어는 이전에 얻은 이름을 사용하여 쉘에서 버전을 요청하는 것입니다.
<some_shell> --version
sh 다른 사람들이 유용한 무언가를주는 동안 종료 코드 2로 실패하는 것처럼 보입니다 (그러나 내가 가지고 있지 않기 때문에 모든 것을 확인할 수는 없습니다).
$ sh --version
sh: 0: Illegal option --
echo $?
2
이것은 매우 깨끗한 솔루션은 아니지만 원하는 작업을 수행합니다.
# MUST BE SOURCED..
getshell() {
local shell="`ps -p $$ | tail -1 | awk '{print $4}'`"
shells_array=(
# It is important that the shells are listed in descending order of their name length.
pdksh
bash dash mksh
zsh ksh
sh
)
local suited=false
for i in ${shells_array[*]}; do
if ! [ -z `printf $shell | grep $i` ] && ! $suited; then
shell=$i
suited=true
fi
done
echo $shell
}
getshell
이제 사용할 수 있습니다 $(getshell) --version.
그러나 이것은 KornShell 과 유사한 쉘 (ksh) 에서만 작동합니다 .
dash, yash당신이 사용하는 경우 등 일반적으로 bash, zsh, ksh당신은 그런 것들에 대해 신경 안 - 무엇이든.
ksh는 bash'기능 세트가 대부분 기능의 하위 세트 이기 때문에 이것이 의미하는 바입니다 .
쉘이 Dash / Bash를 사용하고 있는지 확인하려면 다음을 수행하십시오.
ls –la /bin/sh:
결과가 /bin/sh -> /bin/bash==> 인 경우 쉘은 Bash를 사용하고 있습니다.
결과가 /bin/sh ->/bin/dash==> 인 경우 쉘은 Dash를 사용하고 있습니다.
Bash에서 Dash로 또는 그 반대로 변경하려면 아래 코드를 사용하십시오.
ln -s /bin/bash /bin/sh (쉘을 Bash로 변경)
참고 : 위의 명령으로 / bin / sh가 이미 존재한다는 오류가 발생하면 / bin / sh를 제거하고 다시 시도하십시오.
아래 명령을 사용하십시오.
ps -p $$ | tail -1 | awk '{print $4}'
echo $SHELL당신이하려는 일을하고 잘합니다. $SHELL환경 변수에는 현재 실행중인 쉘이 아닌 현재 사용자의 기본 쉘이 포함되어 있기 때문에 두 번째 것도 좋지 않습니다. 내가 예에 대한 경우 bash기본 쉘로 설정, 실행 zsh하고 echo $SHELL, 그것을 인쇄 할 수 있습니다 bash.
echo $SHELL쓰레기 일 수 있습니다 : ~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$
이것은 RHEL ( Red Hat Linux ), macOS, BSD 및 일부 AIX에서 잘 작동합니다 .
ps -T $$ | awk 'NR==2{print $NF}'
또는 pstree 를 사용할 수있는 경우 다음 중 하나가 작동해야 합니다.
pstree | egrep $$ | awk 'NR==2{print $NF}'
!대체 기능을 수행 합니까?)는 셸 이름을 찾는 것보다 이식성이 뛰어납니다. 지역 관습은/bin/sh실제로 애쉬, 대시, 배쉬 등의 이름을 가진 무언가를 실행하게 할 수도 있습니다 .