Как преодолеть несовместимость между ksh в Linux иустановленный на AIX/Solaris/HPUX?
Вопрос
Я участвую в процессе портирования системы, содержащей несколько сотен 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».
Мои вопросы:
- Есть ли переменная среды, которую я могу настроить, чтобы заставить KSH от Linux вести себя как другая ОС '?В противном случае:
- Есть ли в Linux ksh возможность получить необходимое поведение?В противном случае:
- Существует ли реализация ksh для Linux с желаемым поведением?
Другие примечания:
- В 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 за ранее принятый ответ.
Решение 2
После некоторых советов людей из моей компании мы решили внести в код следующую модификацию.Это дает нам одинаковый результат при использовании «настоящих» 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 за предыдущий принятый ответ.
Другие советы
Вместо использования pdksh в Linux используйте «настоящий» ksh с сайта kornshell.org.pdksh — это слепая повторная реализация ksh.kornshell.org — это оригинальная оболочка Korn, созданная примерно 25 лет назад (написанная Дэвидом Корном).AIX и Solaris используют версии исходного ksh, поэтому версия kornshell.org обычно полна функций и ошибок.Имея опыт работы с SunOS/Solaris, установка kornshell.org ksh обычно является одним из первых действий, которые я делаю на новом компьютере с Linux...
Я установил «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.В ОС «Настоящий Unix» по умолчанию будет установлена версия оболочки Korn AT&T, а не pdksh, поскольку они основаны на AT&T Unix (System V) :-).
Причина различий заключается в том, выполняется ли внутренний блок в исходном контексте оболочки или в подоболочке.Вы можете контролировать это с помощью команд группировки () и {}.Использование временного файла, как при обновлении, будет работать большую часть времени, но может возникнуть проблема, если сценарий запускается дважды быстро или выполняется без очистки файла и т. д.
#!/bin/ksh
flag=false
echo "a\nb" | { while read x
do
flag=true
done }
echo "flag = ${flag}"
exit 0
Это может помочь решить проблему, с которой вы столкнулись в Linux ksh.Если вы используете круглые скобки вместо фигурных скобок, вы получите поведение Linux в других реализациях ksh.
Вот еще одно решение проблемы эха " "
Шаги:
- Найти имя пакета ksh
$ rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" | grep "ksh"
ksh-20100621-19.el6_4.3(x86_64)
удалить КШ
$ sudo yum remove ksh-20100621-19.el6_4.3.x86_64
загрузите pdksh-5.2.14-37.el5_8.1.x86_64.rpm (пожалуйста, проверьте 32-битную или 64-битную ОС и выберите правильный пакет)
Установите 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
После установки ПДКШ
==============
Использование:НАЧИНАТЬ
./ora_db_start_stop.sh START ALL
ИЛИ
./ora_db_start_stop.sh START ONE_OR_MORE
==============
Использование:ОСТАНАВЛИВАТЬСЯ
./ora_db_start_stop.sh STOP ALL
ИЛИ
./ora_db_start_stop.sh STOP ONE_OR_MORE
Я не знаю какого-либо конкретного способа заставить ksh быть совместимым с определенной старой версией.Тем не менее, возможно, вы могли бы установить очень старую версию ksh на свой Linux-систему и обеспечить ее совместимое поведение?
Возможно, будет проще установить более современную версию оболочки amy на компьютеры AIX/HP-UX и просто перенести свои сценарии на использование sh.Я знаю, что существуют версии bash для всех платформ.
Ваш скрипт дает правильный (истинный) вывод, когда zsh
используется с emulate -L ksh
вариант.Если все остальное не помогло, вы можете попробовать использовать zsh
на Линуксе.
Вам обязательно оставаться в пределах КШ?
Даже если вы используете один и тот же ksh, вы все равно будете вызывать все виды внешних команд (grep, ps, cat и т. д.), часть из них будет иметь разные параметры и разные выходные данные от системы к системе.Либо вам придется принять во внимание эти различия, либо использовать версию GNU каждого из них, чтобы сделать вещи одинаковыми.
А Перл Язык программирования изначально был разработан именно для решения этой проблемы.Он включает в себя все функции, которые программист Unix Shell хотел бы от программы He Shell, но он одинаково в каждой системе UNIX.Возможно, у вас не будет последней версии во всех этих системах, но если вам нужно что -то установить, возможно, лучше установить Perl.