Como posso obter com segurança a versão do ksh?

12

Como posso seguramente obter a versão do ksh dentro de um script ksh?

Eu tenho visto as seguintes soluções :

  1. ksh --version
  2. echo ${.sh.version}
  3. echo $KSH_VERSION

E, dadas as circunstâncias certas, cada uma delas funciona corretamente. No entanto, eu me preocupo com o caso não perfeito.

Especificamente, existem várias máquinas com as quais trabalho que possuem versões mais antigas do ksh que, para meus propósitos, estão com falta de funcionalidade. De qualquer forma, a razão que eu quero verificar a versão (programaticamente) é para ver se a versão do ksh é uma das versões menos capazes; e se assim for, eu quero executar um ramo com código menos impressionante.

No entanto, nas máquinas problemáticas, a inépcia do shell se estende à verificação da versão ...

  • Se eu tentar ksh --version , ele não imprime nada e abre uma nova instância de ksh !
  • Se eu tentar echo ${.sh.version} , ksh tratará isso como um erro de sintaxe que não pode ser descartado com 2> /dev/null .

    $ echo ${.sh.version} 2> /dev/null  
    ksh: ${.sh.version}: bad substitution
    
  • É claro que echo $KSH_VERSION parece funcionar bem - quero dizer que não irá falhar - embora nessas máquinas esteja em branco. Além disso, vi algum lugar que KSH_VERSION é definido apenas por pdksh .

Perguntas:

  • Como posso verificar com segurança a versão de ksh programaticamente? Para os meus propósitos aqui, eu realmente não me importo qual é o número da versão atual, apenas se é uma versão desatualizada de ksh .
  • O $KSH_VERSION é bom o suficiente? Quero dizer, se estiver em branco, então é ksh necessariamente uma versão desatualizada? Esse outro fórum estava correto de que talvez não fosse definido mesmo para versões mais recentes de ksh ?
  • Existe apenas uma maneira de verificar isso?
por Sildoreth 01.05.2015 / 20:27

7 respostas

2

Enquanto escrevia um script para ksh , notei que a opção -a do comando whence interno do ksh parece não ser suportada em versões anteriores de ksh . E isso parece ser verdade em todos os sistemas que eu verifiquei, incluindo Solaris, AIX, HP-UX e Linux.

Então aqui está a solução como uma função ksh:

is_modern_ksh() {
  if whence -a whence > /dev/null 2>&1 ; then
    return 0 #success -> true
  fi
  #Else the call to 'whence' failed because '-a' is not supported
  return 1 #failure -> false
}

E aqui está como usá-lo:

if is_modern_ksh ; then
  echo "You're using a MODERN version of ksh. :)"
else
  echo "You're using an OLD version of ksh. :("
fi
    
por 05.05.2015 / 21:19
7

Acho que .sh.version existe desde a primeira versão do ATT ksh 93. Não está disponível em pdksh ou mksh. Como ${.sh.version} é um erro de sintaxe em shells diferentes de ksh93, envolva o teste para ele em um subshell e proteja-o atrás de eval .

_sh_version=$(eval 'echo "${.sh.version}"' 2>/dev/null) 2>/dev/null
case $_sh_version in
  '') echo "This isn't ATT ksh93";;
  …
esac

KSH_VERSION começou no ksh clone de domínio público (pdksh), e foi adicionado ao shell Korn real há relativamente pouco tempo, em 2008 com ksh93t.

Em vez de testar um número de versão, você deve testar o recurso específico que está causando dor. A maioria dos recursos pode ser testada ao tentar alguma construção em um subshell e ver se ele dispara um erro.

    
por 02.05.2015 / 00:17
6

KSH_VERSION não foi implementado em ksh93 antes da versão 93t. Ele será definido em mksh , pdksh , lksh . Então, para verificar a versão de ksh , podemos tentar estas etapas:

  • Verificando KSH_VERSION para detectar mksh , pdksh , lksh
  • Se a primeira etapa falhar, tente um recurso diferente entre ksh93 e ksh88/86 ( Deixe David Korn nos mostrar ).

Com isso em mente, irei:

case "$KSH_VERSION" in
  (*MIRBSD*|*PD*|*LEGACY*) printf '%s\n' "$KSH_VERSION" ;;
  (*) [ -z "$ERRNO" ] && printf '%s\n' "${.sh.version}" || echo ksh88/86 ;;
esac
    
por 01.05.2015 / 21:30
5

Para liberações% "real" ksh (ou seja, baseadas em AT & T), eu uso este comando:

strings /bin/ksh | grep Version | tail -2 

Aqui estão várias saídas que recebo:

Original ksh:

@(#)Version M-11/16/88i

dtksh;

@(#)Version 12/28/93
Version not defined

Moderno ksh93:

@(#)$Id: Version AJM 93u+ 2012-08-01 $

Para pdksh / msh ksh clones e AT & T ksh versões modernas, aqui está algo que funciona:

$ mksh -c 'echo $KSH_VERSION'
@(#)MIRBSD KSH R50 2015/04/19

Editar:

Eu esqueci que você estava perguntando sobre como fazer isso dentro de um script, não conhecendo o caminho para o binário do ksh testado.

Supondo que você realmente quer a versão de ksh usada, e não os recursos que ela suporta, aqui está uma maneira de fazer isso usando apenas o comando strings que deve funcionar no Linux e Solaris:

echo $(for i in $(find /proc/$$ ! -type d ! -name "pagemap" | 
  grep -v "/path/" | grep -v "/fd/" ) ; do
  strings $i | egrep "([V]ersion|[K]SH_VERSION).*[0-9]" | sort -u
done 2>/dev/null)

Observe que esse método não é confiável, pois /proc pode não ser montado, e certamente há outras deficiências. Não foi testado em outros sistemas operacionais Unix.

    
por 01.05.2015 / 21:41
1

CTRL + ALT + V

ou

ESC , CTRL + v

Tipicamente, provou ser muito confiável quanto à determinação interativa da versão do KSH que você está usando, no entanto, a criação de scripts se mostrou mais difícil.

    
por 02.05.2015 / 05:42
0

Eu acho que o problema fundamental com o uso de $ {. sh.version} é que o ksh88 simplesmente pára, com um código de saída diferente de zero.

Então, minha solução é colocar o código que faz referência a $ {. sh.version} em um sub-shell, depois testar para ver se o sub-shell sai diferente de zero e tem código no sub-shell que funcionará nas versões do ksh onde referenciar $ {. sh.version} funciona. Envolvê-lo em uma função que é então chamada por outra função que inverte o código de retorno, para que a chamada final esteja verificando a verdadeira.

function is_oldksh
{
    (test -n ${.sh.version}) 2>/dev/null
}

function oldkshtest
{

    is_oldksh || return 0 && return 1
}

oldkshtest && echo "old ksh" || echo "new ksh"

Eu executei isso no AIX e no Oracle Enterprise Linux 5 & 6, com ksh88, ksh93 e pdksh.

Pete

    
por 23.10.2015 / 13:17
0

O seguinte parece funcionar razoavelmente bem para todos os shells que eu testei, incluindo o antigo ksh88e e uma quase completa gama de clones comuns do Ksh (embora apenas uma versão de cada um), embora eu ainda não tenha testado um original real Bourne shell (e isso pode exigir a adaptação da expressão test para versões mais antigas ...

Adendo:

Eu também testei isso com sucesso com o Heirloom Bourne Shell, embora com um programa test externo (e mais moderno).

is_attksh()
{
    # ksh93
    _sh_version=$(eval 'echo "${.sh.version}"' 2>/dev/null)
    # pdksh only
    _opt_login=$(set -o | grep login)

    test -n "${_sh_version}" -o \( -z "${_opt_login}" -a -n "${_}" -a -n "${ERRNO}" -a -n "${FCEDIT}" -a -n "${PS3}" \)
}
is_attksh && echo "AT&T Ksh${_sh_version:+: }${_sh_version:- (probably ksh88 or ksh86)}" || echo "not real ksh"

is_zsh()
{
    test -n "${ZSH_VERSION}"
}
is_zsh && echo "Zsh: ${ZSH_VERSION}" || echo "not zsh"
    
por 04.08.2017 / 21:32