Jak mogę bezpiecznie pobrać wersję ksh ze skryptu ksh?
Ja widziałem następujące rozwiązania :
ksh --version
echo ${.sh.version}
echo $KSH_VERSION
Biorąc pod uwagę odpowiednie okoliczności, każda z nich działa poprawnie. Dbam jednak o niedoskonały przypadek.
W szczególności istnieje kilka maszyn, z którymi współpracuję, które mają starsze wersje ksh, które, moim zdaniem, są bardzo pozbawione funkcjonalności. W każdym razie powodem, dla którego chcę sprawdzić wersję (programowo), jest sprawdzenie, czy wersja ksh jest jedną z mniej zdolnych wersji; a jeśli tak, chcę wykonać gałąź z mniej niesamowitym kodem.
Jednak na problematycznych maszynach nieudolność powłoki rozciąga się na sprawdzenie wersji ...
- Jeśli spróbuję
ksh --version
, nic nie drukuje i otwiera nową instancjęksh
! Jeśli spróbuję
echo ${.sh.version}
,ksh
potraktuje to jako błąd składniowy, którego nie można usunąć2> /dev/null
.$ echo ${.sh.version} 2> /dev/null ksh: ${.sh.version}: bad substitution
Oczywiście
echo $KSH_VERSION
wydaje się, że działa dobrze - mam na myśli to, że się nie zawiesi - choć na tych komputerach jest pusty. Również widziałem gdzieś , żeKSH_VERSION
jest ustawiony tylkopdksh
.
Pytania:
- Jak mogę bezpiecznie sprawdzić wersję
ksh
programowo? Dla moich celów nie obchodzi mnie, jaki jest rzeczywisty numer wersji, tylko czy jest to przestarzała wersjaksh
. - Czy
$KSH_VERSION
wystarczy? Mam na myśli to, że jeśli jest puste, toksh
koniecznie jest nieaktualna wersja? Czy to drugie forum było prawidłowe, że może nie być ustawione nawet dla nowszych wersjiksh
? - Czy po prostu w ogóle nie można tego sprawdzić?
źródło
PS1
do korzystania z tej funkcji. Jednak Old ksh nie obsługuje$()
wPS1
. Więc jeśli jest to nowoczesna wersja ksh, chcęPS1
użyć funkcji, którą stworzyłem; jeśli to stara wersja, używam tylko$PWD
.Odpowiedzi:
Myślę, że
.sh.version
istnieje od pierwszej wersji ATT ksh 93. Nie jest dostępny w pdksh ani mksh. Ponieważ${.sh.version}
jest to błąd składniowy w powłokach innych niż ksh93, zawiń test w podpowłoce i chroń goeval
.KSH_VERSION
zaczął w klonie ksh (pdksh) w domenie publicznej i został dodany do rzeczywistej powłoki Korna stosunkowo niedawno, w 2008 roku z ksh93t.Zamiast testować numer wersji, powinieneś przetestować konkretną funkcję, która wywołuje u Ciebie żal. Większość funkcji można przetestować, wypróbowując jakąś konstrukcję w podpowłoce i sprawdzając, czy powoduje to błąd.
źródło
${.sh.version}
jako błąd składniowy, którego nie można pogodzić. Otrzymałem wiadomośćbad substitution
./dev/null
i zignoruj status wyjścia.eval '_sh_version=$(echo "${.sh.version}")' 2>/dev/null
działa lepiej?KSH_VERSION
nie został zaimplementowanyksh93
przed wersją 93t. Będzie on być ustawiony wmksh
,pdksh
,lksh
. Aby sprawdzić wersjęksh
, możemy wypróbować następujące kroki:KSH_VERSION
wykryćmksh
,pdksh
,lksh
ksh93
iksh88/86
( Pokaż nam David Korn ).Mając to na uwadze, pójdę z:
źródło
$KSH_VERSION
nie jest puste? Na moim komputerze Ubuntu wyświetla „ksh93”, aleKSH_VERSION
jest ustawione..kshrc
.ENV
zmienna jest ustawiona (i zwykle jest ustawiona na~/.kshrc
), skrypt na pewno odczyta.kshrc
plik. Oczywiście, byłoby dość dziwne, gdyby skrypt ustawiał fałszywy KSH_VERSION, ale jest to jednak możliwe, podobnie jak jawne wykonanie skryptu przy użyciu innego interpretera niż ten określony w pierwszym wierszu jest możliwą sytuacją.KSH_VERSION
. Imksh
,pdksh
,lksh
,KSH_VERSION
jest oznaczony jako tylko do odczytu.W przypadku „prawdziwych”
ksh
wersji (tj. Opartych na AT&T) używam tego polecenia:Oto różne wyniki, które otrzymuję:
Oryginalny ksh:
dtksh;
Współczesny ksh93:
Dla
pdksh
/msh
ksh
klonów i nowoczesnych wersji AT&Tksh
, oto coś, co działa:Edytować:
Przeoczyłem, że pytasz o zrobienie tego ze skryptu, nie poprzez znajomość ścieżki do testowanego pliku binarnego ksh.
Zakładając, że naprawdę chcesz wersji
ksh
używanej, a nie obsługiwanych przez nią funkcji, oto jeden ze sposobów, aby to zrobić, używając tylkostrings
polecenia, które powinno działać przynajmniej w systemie Linux i Solaris:Zauważ, że ta metoda jest zawodna, ponieważ
/proc
może nie zostać zamontowana, a na pewno istnieją inne słabości. Nie jest testowany na innych systemach uniksowych.źródło
lksh
ipdksh
w Debian Jessie.lksh
ipdksh
nie można ich oddzielićKSH_VERSION
?strings
po nich.KSH_VERSION
zdecydowanie może.ksh
wydań», byłem wyraźnie wyłączając klonów niż AT & T KSH, jakpdksh
,mksh
ilksh
.strings
na niektórych plikach binarnych ksh to zły pomysł, ponieważ nie wiesz, czy to ten, który uruchamia twój skrypt. Może twój skrypt jest uruchamiany przez/usr/local/bin/ksh
lub/home/bob/bin/ksh
lub/bin/sh
lub/usr/posix/bin/sh
albo…Podczas pisania skryptu
ksh
zauważyłem, że-a
opcja wbudowanegowhence
polecenia ksh wydaje się nie być obsługiwana w starszych wersjachksh
. I wydaje się, że tak jest we wszystkich sprawdzonych systemach, w tym w systemach Solaris, AIX, HP-UX i Linux.Oto rozwiązanie jako funkcja ksh:
A oto jak go użyć:
źródło
${.sh.version}
?whence
w Zsh ma-a
whence
polecenie, które nie jest w żaden sposób powiązane z ksh lub jego wersją. Nie wiem nawet, dlaczego chciałbyś sprawdzić, czy ksh jest starą wersją z poziomu instancji zsh, która jest zupełnie inną powłoką./bin/ksh
, np. W Debian Linux. Teraz go tam nie używam (w tej chwili nie mogę zmienić powłoki logowania, żeby sprawdzić), więc nie wiem, czy to czyta.kshrc
, ale podejrzewam, że tak.CTRL+ ALT+V
lub
ESC, CTRL+V
Zazwyczaj okazały się bardzo niezawodne, jeśli chodzi o interaktywne określanie używanej wersji KSH, jednak ich skryptowanie okazało się trudniejsze.
źródło
set -o vi
aby ustawić skróty klawiszowe na vi. Wcześniej, lub z + o vi lub -o emacs, po prostu mi się nie pokazywał. PD KSH v5.2.14 99/07 / 13.2 na openbsd 6.1Myślę, że podstawowym problemem z użyciem $ {. Sh.version} jest to, że ksh88 po prostu zatrzymuje się, z niezerowym kodem wyjścia.
Więc moim rozwiązaniem jest umieszczenie kodu, który odwołuje się do $ {. Sh.version} w podpowłoce, a następnie przetestowanie, aby sprawdzić, czy podpowłoka wychodzi z zera i czy ma kod w podpowłoce, który będzie działał na wersjach ksh, do którego odwołuje się $ {. sh.version}. Zawijanie go w funkcję, która jest następnie wywoływana przez inną funkcję, która odwraca kod powrotu, tak aby końcowe wywołanie sprawdzało, czy jest prawdziwe.
Uruchomiłem to na systemach AIX i Oracle Enterprise Linux 5 i 6 z ksh88, ksh93 i pdksh.
Pete
źródło
.sh.version
(faktycznieKSH_VERSION
jest to alias). Również niektóre powłoki, np. NetBSD sh, po prostu przestają czytać po napotkaniu${.sh.version}
i żadne przekierowanie nie może utrzymać ich działania skryptu.Poniższe wydaje się działać całkiem nieźle dla wszystkich przetestowanych przeze mnie powłok, w tym starego ksh88e i prawie pełnej gamy popularnych klonów Ksh (choć tylko jedna wersja każdego z nich), chociaż nie przetestowałem jeszcze prawdziwej oryginalnej powłoki Bourne'a ( i może to wymagać dostosowania
test
wyrażenia do starszych wersji ...Uzupełnienie:
Teraz z powodzeniem przetestowałem to również w Heirloom Bourne Shell, chociaż z zewnętrznym (i bardziej nowoczesnym)
test
programem.źródło
${.sh.version}
nie mogą być częścią rozwiązania, ponieważ niektóre wersje ksh - wersje, których dotyczył oryginalny post - błąd krytycznie przy tej składni.