Как преодолеть несовместимость между ksh в Linux и установленной в AIX / Solaris / HPUX? - PullRequest
5 голосов
/ 16 сентября 2008

Я участвую в процессе переноса системы, содержащей несколько сотен сценариев ksh, из AIX, Solaris и HPUX в Linux. Я обнаружил следующее различие в поведении ksh в двух системах:

#!/bin/ksh
flag=false
echo "a\nb" | while read x
do
    flag=true
done
echo "flag = ${flag}"
exit 0

В AIX, Solaris и HPUX вывод «flag = true», в Linux вывод «flag = false».

Мои вопросы:

  • Есть ли переменная окружения, которую я могу установить, чтобы Linux ksh вел себя как другие осы '? В противном случае:
  • Есть ли опция в ksh Linux, чтобы получить требуемое поведение? В противном случае:
  • Доступна ли для Linux реализация ksh с требуемым поведением?

Другие примечания:

  • В AIX, Solaris и HPUX ksh является вариантом ksh88.
  • В Linux ksh является общественным достоянием ksh (pdksh)
  • В AIX, Solaris и HPUX dtksh и ksh93 (где они у меня установлены) соответствуют ksh
  • Системы Windows NT, к которым у меня есть доступ: Cygwin и MKS NT, совместимы с Linux.
  • В AIX, Solaris и Linux bash работает согласованно, давая неверный (с моей точки зрения) результат «flag = false».

В следующей таблице приведены проблемы системы:

uname -s       uname -r                   which ksh          ksh version                     flag =
========       ========                   =========          ===========                     ======
Linux          2.6.9-55.0.0.0.2.ELsmp     /bin/ksh           PD KSH v5.2.14 99/07/13.2       false
AIX            3                          /bin/ksh           Version M-11/16/88f             true    // AIX 5.3
                                          /bin/ksh93         Version M-12/28/93e             true
SunOS          5.8, 5.9 and 5.10          /bin/ksh           Version M-11/16/88i             true
                                          /usr/dt/bin/dtksh  Version M-12/28/93d             true
HP-UX          B.11.11 and B.11.23        /bin/ksh           Version 11/16/88                true
                                          /usr/dt/bin/dtksh  Version M-12/28/93d             true
CYGWIN_NT-5.1  1.5.25(0.156/4/2)          /bin/ksh           PD KSH v5.2.14 99/07/13.2       false
Windows_NT     5                          .../mksnt/ksh.exe  Version 8.7.0 build 1859...     false    // MKS

Обновление

После некоторых советов от сотрудников моей компании мы решили внести следующие изменения в код. Это дает нам один и тот же результат, будь то использование "настоящих" ksh (ksh88, ksh93) или любого из клонов ksh (pdksh, MSK ksh). Это также правильно работает с bash.

#!/bin/ksh
echo "a\nb" > junk
flag=false
while read x
do
    flag=true
done < junk
echo "flag = ${flag}"
exit 0

Спасибо jj33 за ранее принятый ответ.

Ответы [ 8 ]

7 голосов
/ 16 сентября 2008

Вместо использования pdksh в linux используйте "настоящий" ksh из kornshell.org. pdksh - это слепая повторная реализация ksh. kornshell.org - это оригинальная оболочка korn, созданная примерно 25 лет назад (написанная Дэвидом Корном). AIX и Solaris используют версии оригинального ksh, поэтому версия kornshell.org, как правило, содержит множество функций и ошибок. Порезав зубы с помощью SunOS / Solaris, установка kornshell.org ksh, как правило, является одной из первых вещей, которые я делаю на новой Linux-системе ...

3 голосов
/ 18 сентября 2008

После некоторых советов от сотрудников моей компании мы решили внести следующие изменения в код. Это дает нам один и тот же результат, будь то использование "настоящих" ksh (ksh88, ksh93) или любого из клонов ksh (pdksh, MSK ksh). Это также правильно работает с bash.

#!/bin/ksh
echo "a\nb" > junk
flag=false
while read x
do
    flag=true
done < junk
echo "flag = ${flag}"
exit 0

Спасибо jj33 за предыдущий принятый ответ.

1 голос
/ 20 марта 2014

Вот еще одно решение проблемы "\ n" для эха

Шаги:

  1. Найти имя пакета ksh

$ rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" | grep "ksh" ksh-20100621-19.el6_4.3(x86_64)

  1. удалить ksh $ sudo yum remove ksh-20100621-19.el6_4.3.x86_64

  2. загрузка pdksh-5.2.14-37.el5_8.1.x86_64.rpm (пожалуйста, проверьте ОС на 32-битную или 64-битную и выберите правильный pkg)

  3. Установить pdksh-5.2.14-37.el5_8.1.x86_64.rpm

$ sudo yum -y install /SCRIPT_PATH/pdksh-5.2.14-37.el5_8.1.x86_64.rpm

Вывод перед установкой PDKSH

$ ora_db_start_stop.sh
\n==============
Usage: START
==============\n\n
./ora_db_start_stop.sh START ALL    \n
OR \n
./ora_db_start_stop.sh START ONE_OR_MORE    \n
\n==============
Usage: STOP
==============\n\n
./ora_db_start_stop.sh STOP ALL    \n
OR \n
./ora_db_start_stop.sh STOP ONE_OR_MORE    \n\n

После установки ПДКШ

==============

Использование: START

./ora_db_start_stop.sh START ALL

OR

./ora_db_start_stop.sh START ONE_OR_MORE

==============

Использование: STOP

./ora_db_start_stop.sh STOP ALL

OR

./ora_db_start_stop.sh STOP ONE_OR_MORE

1 голос
/ 01 ноября 2008

Причина различий заключается в том, выполняется ли внутренний блок в исходном контексте оболочки или в подоболочке. Вы можете управлять этим с помощью команд группировки () и {}. Использование временного файла, как вы делаете в своем обновлении, будет работать большую часть времени, но столкнется с проблемами, если скрипт выполняется дважды быстро, или если он выполняется без очистки файла и т. Д.

#!/bin/ksh
flag=false
echo "a\nb" | { while read x
do    
     flag=true
done }
echo "flag = ${flag}"
exit 0

Это может помочь с проблемой, с которой вы столкнулись в Linux ksh. Если вы используете скобки вместо скобок, вы получите поведение Linux в других реализациях ksh.

1 голос
/ 16 сентября 2008

Я установил 'ksh' и 'pdksh' в моей локальной системе Ubuntu Hardy.

ii  ksh            93s+20071105-1 The real, AT&T version of the Korn shell
ii  pdksh          5.2.14-21ubunt A public domain version of the Korn shell

ksh имеет «правильное» поведение, которого вы ожидаете, а pdksh - нет. Вы можете проверить программный репозиторий вашего локального дистрибутива Linux на наличие «настоящего» ksh вместо использования pdksh. Операционные системы "Real Unix" собираются установить версию оболочки Korn AT & T, а не pdksh, по умолчанию, что на основе ОС AT & T Unix (System V): -).

0 голосов
/ 17 сентября 2008

Вы должны оставаться в пределах КШ?

Даже если вы используете тот же ksh, вы все равно будете вызывать все виды внешних команд (grep, ps, cat и т. Д.), Часть из них будет иметь разные параметры и различный вывод из системы в систему. Либо вам придется учесть эти различия, либо использовать версию GNU каждого из них, чтобы все было одинаково.

Язык программирования Perl изначально был разработан именно для того, чтобы решить эту проблему. Он включает в себя все функции, которые программист оболочки Unix хотел бы получить от программы оболочки, но это то же самое в каждой системе Unix. У вас может не быть последней версии на всех этих системы, но если вам нужно что-то установить, возможно, лучше установить perl.

0 голосов
/ 16 сентября 2008

Ваш скрипт выдает правильный (true) вывод, когда zsh используется с опцией emulate -L ksh. Если ничего не помогает, вы можете попробовать zsh в Linux.

0 голосов
/ 16 сентября 2008

Я не знаю какой-либо конкретной опции, чтобы заставить ksh быть совместимым с определенной более старой версией. Тем не менее, возможно, вы могли бы установить очень старую версию ksh на вашем Linux-устройстве и вести себя совместимым образом?

Возможно, будет проще установить более современную версию оболочки amy на блоках AIX / HP-UX и просто перенести сценарии на sh. Я знаю, что существуют версии bash для всех платформ.

...