كيفية التغلب على عدم التوافق بين 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 هي قذيفة كورن الأصلية التي يعود تاريخها إلى 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.سيقوم نظام التشغيل "Real Unix" بتثبيت إصدار AT&T من Korn Shell، بدلاً من pdksh، بشكل افتراضي، والذي يعتمد على AT&T Unix (النظام 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)
إلغاء تثبيت ksh
$ sudo yum remove ksh-20100621-19.el6_4.3.x86_64
قم بتنزيل pdksh-5.2.14-37.el5_8.1.x86_64.rpm (يرجى التحقق من نظام التشغيل 32 بت أو 64 بت واختيار pkg الصحيح)
تثبيت 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
بعد تثبيت PDKSH
==============
الاستخدام:يبدأ
./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 Shell على صناديق AIX/HP-UX، وما عليك سوى ترحيل البرامج النصية الخاصة بك لاستخدام sh.أعلم أن هناك إصدارات من bash متاحة لجميع الأنظمة الأساسية.
يعطي البرنامج النصي الخاص بك الإخراج الصحيح (الحقيقي) عندما zsh
يستخدم مع emulate -L ksh
خيار.إذا فشل كل شيء آخر قد ترغب في محاولة استخدام zsh
على لينكس.
هل يجب عليك البقاء في حدود ksh؟
حتى لو كنت تستخدم نفس ksh، فسوف تستمر في استدعاء جميع أنواع الأوامر الخارجية (grep، ps، cat، إلخ...) وسيكون لجزء منها معلمات مختلفة ومخرجات مختلفة من نظام إلى آخر.إما أنه سيتعين عليك أن تأخذ هذه الاختلافات في الاعتبار أو تستخدم إصدار GNU لكل واحد منهم لجعل الأمور متشابهة.
ال بيرل تم تصميم لغة البرمجة في الأصل خصيصًا للتغلب على هذه المشكلة.ويشمل جميع الميزات التي يريدها مبرمج Unix Shell من برنامج SHELL ، ولكنه هو نفسه في كل نظام UNIX.قد لا يكون لديك أحدث إصدار في جميع هذه الأنظمة ، ولكن إذا كنت بحاجة إلى تثبيت شيء ما ، فربما يكون من الأفضل تثبيت Perl.