KornShell - глобально установить флаг "-x" - PullRequest
8 голосов
/ 16 февраля 2010

Есть ли способ установить режим отладки ( set -x ) для сценария KornShell (ksh) глобально? В настоящее время кажется, что я сделал что-то вроде следующего:

a(){
   set -x
   #commands
}

b(){
   set -x
   #more commands
}

set-x 
a
#commands
b

Мне бы очень хотелось, чтобы команда set-x вызывалась только в одном месте.

Примечание: Это все в KSH88 в AIX.

Пример:

#!/bin/ksh
set -x

a(){
   echo "This is A!"
}

b(){
   echo "This is B!"
}

a
echo "Outside"
b
dev2:/home/me-> ./testSetX
+ a
This is A!
+ echo Outside
Outside
+ b
This is B!
dev2:/home/me->

Ответы [ 5 ]

8 голосов
/ 16 февраля 2010

Это ksh88 на машине HP-UX:

me@host ..dev/
$ cat ./test/verbose
#!/bin/ksh
set -x

hello() {
  print $1
}

hello kapow!
exit

me@host..dev/
$ ./test/verbose    
+ hello kapow!
+ print kapow!
kapow!
+ exit

Он уверен, выглядит , что работает нормально. Я подтвердил, что он также работает с «set -x» где угодно до первого вызова функции.

Я перешел на систему AIX и столкнулся с проблемой, которую вы описали. Если в AIX ksh88 функции определены как function a { или a() {, set -x не переходит в область действия функции. При переключении на ksh93 в том же окне AIX функции, объявленные с использованием нового синтаксиса function a {, также не переносят внешний set -x во внутреннюю область. Однако ksh93 ведет себя так же, как POSIX sh (и ksh88 на других платформах), который вел себя, передавая set -x в функцию, когда функция определена в старом методе a(){. Вероятно, это связано с обратной совместимостью в ksh93, где он пытается эмулировать старое поведение, когда функции определены старым способом.

Следовательно, вы можете временно переключить интерпретатор на ksh93 для целей отладки, а затем переключиться обратно на ksh88, если вам не нравятся более длинные массивы, ассоциативные массивы, математика с плавающей запятой, поддержка пространства имен и rugly 10-кратное улучшение скорости исполнения, которую приносит ksh93. ;) Потому что, похоже, ответ «нет, вы не можете этого сделать» с ksh88 в AIX. (

4 голосов
/ 15 апреля 2013

Я протестировал глобальный set -x с помощью ksh88 (в Solaris 10) и ksh93 (Fedora 17), и обе глобальные команды set -x в верхней части скрипта не имеют функционально-локальной области видимости (то есть не имеют есть локальные эффекты).

В качестве обходного пути вы можете включить локальную трассировку команд для всех функций в области (после того, как они определены) и до их вызова с помощью typeset:

$ cat test.ksh
PS4='$LINENO: '

set -x

function foo {
  print Hello
}

bar() {
  print World
}

typeset -ft `typeset +f` 

foo
bar

Вывод под ksh88 (Solaris 10):

$ ksh test.ksh 
13: typeset +f
13: typeset -ft bar foo
15: foo
1: print Hello
Hello
16: bar
1: print World
World

набрано закомментировано

$ ksh test.ksh 
15: foo
Hello
16: bar
World

Вывод в ksh93 (Fedora 17):

$ ksh test.ksh
13: typeset +f
13: typeset -ft 'bar()' foo
15: foo
6: print Hello
Hello
16: bar
10: print World
World

набрано закомментировано

$ ksh test.ksh
15: foo
Hello
16: bar
10: print World
World

Вывод под bash

typeset закомментировано и print заменено на эхо:

$ bash test.ksh
15: foo
6: echo Hello
Hello
16: bar
10: echo World
World

(bash 4.2.39 (1) на Fedora 17)

Тот же вывод в zsh 5.0.2 на Fedora 17.

Заключение

При использовании Ksh только с ksh93 и синтаксисом определения функции fnname() глобальный set -x также имеет локальную область действия. Обходной путь на основе typeset -ft - это относительно легкий способ включить трассировку команд для всех функций.

В bash (и zsh) глобальный set -x работает должным образом, то есть он также имеет локальную область видимости для всех функций.

Таким образом, при написании новых сценариев использование bash вместо ksh может быть лучшей альтернативой из-за этого.

В качестве примечания: bash, вероятно, даже более переносим, ​​чем ksh88 - особенно более переносим, ​​чем ksh93.

4 голосов
/ 16 февраля 2010

Добавьте это к своей линии Шебанга:

#!/bin/ksh -x

Или установите его в верхней части вашего скрипта:

#!/bin/ksh
set -x

Или запустите ваш скрипт из командной строки:

ksh -x script_name
1 голос
/ 03 февраля 2012

Поведение "set -x" - это "особенность" оболочки AIX (не говоря о мозге d ...).

Вы попросили "способ установить режим отладки ... глобально". Вот что я делаю для достижения этой цели:

set_x="${set_x-:}"; # Defaults to ":" (NOOP) unless already non-empty
# Using ":" instead of "" makes termination via semicolon work,
# which in turn allows inlining, especially when using SSH.
# Alternatively, if tracing should be on by default:
#set_x="${set_x-set -x}"; # Defaults to "set -x" unless already non-empty

$set_x; # Apply to file scope

f() {
    $set_x; # Apply to local scope
    echo working...;
}
main() {
    $set_x; # Apply to local scope
    f;
    ssh localhost $set_x\; hostname; # Apply to remote shell scope
    ssh localhost "set_x=\"$set_x\" foo"; # Apply to foo called in remote shell
}
main;

Чтобы включить трассировку, установите $set_x в среде вашего скрипта на "set -x". Чтобы управлять этим на основе каждого вызова, добавьте к вызову префикс "set_x='set -x'". Поскольку используется переменная среды, этот метод естественным образом работает с вложенными вызовами.

Все эти случаи использования $set_x; немного уродливы, но работают со всеми оболочками, и выгода обычно перевешивает стоимость.

Другой пример "особенности" оболочки AIX:

set -e;
trap "echo trapped at file scope" EXIT;
f() { return 1; }
main() { f; }
main;

Вышеприведенное должно выводить «trapped at file scope», но ничего не печатать.

1 голос
/ 05 августа 2011

Имейте в виду, что область видимости затрагивается между двумя типами объявлений функций

a () { }

против.

function a { }

В частности, набор текста в ksh не работает так, как вы ожидаете в первом случае. Обнаружено при попытке отладки скрипта с помощью рекурсивной функции. Подробнее здесь:

http://www.dartmouth.edu/~rc/classes/ksh/functions.html

...