Как исправить сценарий оболочки, чтобы он распознавал символ новой строки на другом сервере под управлением Linux?

Символ новой строки правильно распознается на сервере server2 (Solaris), тогда как на сервере server1 (Linux) он воспринимается как символ обратной косой чертыn. Как это исправить?

Работая над простым скриптом, который принимает аргументы и отправляет письма, я впервые заметил это довольно странное поведение.

Синтаксис: $ ksh SEND_MAIL.sh <to> <Subject> <body>

  1. Теперь, когда я запускаю этот скрипт на сервере-1

    [kent@server1] $ ksh SEND_MAIL.sh [email protected] "Subject" "123\n456" [четверг, 10 января, 10:51:18 EST 2013] — Начинается отправка почты на адрес: [email protected], с тема \'>>>123\n456\'

    Обратите внимание, что символ новой строки принимается как backlash-n.

  2. В то время как на сервере-2 специальный символ \n правильно заменяется на символ новой строки.

    [kent@server2] $ ksh SEND_MAIL.sh [email protected] "Subject" "123\n456" [четверг, 10 января, 10:51:18 EST 2013] — Начинается отправка почты на адрес: [email protected], с тема \'>>>123 456\'

Я думаю, что мне может понадобиться изменить некоторые переменные среды KornShell, но я не могу понять это.

ОБНОВЛЕНИЕ:

После приведенного ниже руководства Хенка... Я вижу, что знания разницы недостаточно, чтобы помочь мне решить основную проблему - то есть, чтобы скрипт на server1 распознавал символы \n как новую строку. Итак, я улучшил свой вопрос.


Примечания:

Server1 — это сервер Linux, а Server2 — Solaris.


Сведения об окружении > KornShell: — предложено Хэнком Лангевельдом.

На сервере1:

[kent@server1]$ ksh --version
  version         sh (AT&T Research) 93t+ 2010-02-02
[kent@server1]$ echo ${.sh.version}
bash: ${.sh.version}: bad substitution
[kent@server1]$ [ "${ERRNO}" ] && echo ksh88 || echo ksh93
ksh93
[kent@server1]$ [ "`echo "\c" | grep c`" ] && echo ksh93 || echo ksh88 
ksh93

На сервере2:

# I'm am in bash
[kent@server2]$ ksh --version 
$
$ ksh --version
$ 
[kent@server2]$ echo ${.sh.version}
bash: ${.sh.version}: bad substitution
[kent@server2]$ [ "${ERRNO}" ] && echo ksh88 || echo ksh93
ksh93
[kent@server2]$ [ "`echo "\c" | grep c`" ] && echo ksh93 || echo ksh88 
ksh93

На серверах 1 и 2 я получаю одинаковое поведение:

$ echo -e "1\n2"
1
2
$ echo "1\n2"
1\n2
$ echo $'1\n2'
1
2

Код:

SEND_MAIL.sh

#Syntax: $ ksh SEND_MAIL.sh <to> <Subject> <body>
TO_REC=$1
SUBJECT=$2
MESSAGE=$3
echo "$MESSAGE"| mailx -s "$SUBJECT" $TO_REC

Поместите строку set | grep SH в сценарий на обоих серверах, чтобы проверить, на какой оболочке он работает, как предложено Oliver ниже.

На сервере1:

[kent@server1]$ ksh SEND_MAIL.sh [email protected] "Subject" ">>>123\n\n456$a"
KSH_VERSION=.sh.version
SHELL=/bin/bash
SHLVL=3
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SSH_CLIENT='3.209.100.144 59645 22'
SSH_CONNECTION='3.209.100.144 59645 3.56.9.127 22'
SSH_TTY=/dev/pts/1
...

На сервере2:

[kent@server2]$ ksh SEND_MAIL.sh [email protected] "Subject" ">123\n\n456$a"
SHELL=/bin/ksh
SHLVL=1
SSH_CLIENT='3.209.100.144 49351 22'
SSH_CONNECTION='3.209.100.144 49351 3.56.29.159 22'
SSH_TTY=/dev/pts/2
...

person Kent Pawar    schedule 10.01.2013    source источник
comment
Скрипт может и не при чем. У вас такое же поведение при передаче строки простой команде unix (например, echo)?   -  person Khaur    schedule 10.01.2013
comment
larsmans - я добавил код. @Khaur - Пожалуйста, ознакомьтесь с разделом «поведение» выше. Спасибо.   -  person Kent Pawar    schedule 11.01.2013


Ответы (4)


Это AST ksh93, pdksh или старый ksh88?

Вот как вы можете проверить версию вашего ksh, проверив вывод ksh --version и значение ${.sh.version}

$ ksh --version
version         sh (AT&T Research) 93u+ 2012-06-26
$ ksh -c 'echo ${.sh.version}'
Version AJM 93u+ 2012-06-26

Затем сообщите нам, совпадают ли результаты на двух серверах. Старые версии ksh могут сообщать об ошибке.


Решение для кш93:

На server1 вставьте свой \n в ksh93 Ansi string, заключив его в $' и ':

two_lines=$'one\ntwo'  && print "$two_lines"
one
two

Это экстраполирует любые побеги в стиле C.

person Henk Langeveld    schedule 11.01.2013
comment
Я обновил свой пост выводами. Похоже, что они оба используют одну и ту же версию оболочки korn. - person Kent Pawar; 11.01.2013
comment
Незначительное редактирование, чтобы гарантировать, что эхо ${.sh.version} действительно выполняется ksh. На ваших серверах работают разные оболочки, как объяснено в моем последующем ответе. Я пытался объединить это здесь, но получилось грязно. – 11 часов назад исправлена ​​опечатка - person Henk Langeveld; 12.01.2013
comment
Проблема со строками ANSI заключается в том, что это позволит вам использовать внутри них переменные UNIX. Итак, как мне получить символ новой строки, а также правильно расширить переменные UNIX? - person Kent Pawar; 21.01.2013
comment
Привет, Кент, создайте константы оболочки для специальных символов, используя строки ANSI (NL=$'\n'). Затем объедините их все в строку с двойными кавычками ( message="$line_one${NL}$line_two" ) - person Henk Langeveld; 21.01.2013
comment
Спасибо @Henk, я так и сделаю. Я ценю ваше руководство с этой проблемой. - person Kent Pawar; 22.01.2013

см., на каждом сервере:

  • версия кш
  • в какой оболочке вы вошли при попытке: grep kent /etc/passwd покажет оболочку входа в последнем поле).
  • И сделайте head -n 1 /path/to/SEND_MAIL.sh, чтобы увидеть, есть ли у одного или другого другой «шебанг».
  • И, наконец, поместите строку set | grep SH в другой скрипт, скажем, ./test.sh, а затем chmod +x ./test.sh, и запустите его: ./test.sh: чтобы увидеть, запускается ли он с другой оболочкой на каждом сервере.
person Olivier Dulac    schedule 10.01.2013
comment
Шебанг не имеет значения: скрипты вызываются явно с помощью ksh. Shebang имеет значение только в том случае, если вы выполняете скрипт напрямую. - person me_and; 11.01.2013
comment
Привет, Оливье, код идентичен, поэтому проблема не в шебанге. Пожалуйста, посмотрите мой пост, я обновил его выводом. Также grep kent /etc/passwd не работает, так как мы используем LDAP, поэтому моей учетной записи нет в /etc/passwd.. Я не слишком знаком с этим.. - person Kent Pawar; 11.01.2013

Два сервера имеют разные ksh исполняемые файлы. Сервер 1 — это самый последний ksh93 от AT&T, поставляемый в комплекте с большинством систем Linux (производные debian и EL). Сервер 2 - индивидуалист. Возможно, это pdksh? Это объясняет различия, которые вы видите.

На сервере1:

[kent@server1]$ ksh --version
  version         sh (AT&T Research) 93t+ 2010-02-02

На сервере2:

# I'm am in bash
[kent@server2]$ ksh --version 
$
person Henk Langeveld    schedule 11.01.2013

Для оболочки korn в Linux попробуйте print или printf вместо echo. Это подходит для меня. В настоящее время я использую его для переноса своих сценариев с AIX на Linux. Я не проверял все возможные контексты, но пока он работает хорошо. Другой вариант, который я пробовал до этого, также работает:

В каком-нибудь установочном файле env, таком как .profile, добавьте следующий оператор:

Затем замените все \n на ${NL}, фигурные скобки необходимы, так как вы не хотите, чтобы то, что следует за $NL, рассматривалось как часть имени переменной окружения.

Удачи

person Muthuswamy K Bharadwaj    schedule 24.03.2015