2016-12-26 4 views
0

Во-первых, я не уверен, правильно ли сформулировал вопрос. Итак, у меня есть сценарий bash, который удаляет пользователя в системе. Проблема заключается в том, что перед кодом терминала отображается сообщение об ошибке msg. Здесь. Код:Bash script stderr и stdout

echo -e "\nCommencing user $UserName removal" 
echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)" 
echo -e "Listing group(s) user: " "$(groups $UserName)" 
echo -e "Removing Crontab ... " "$(crontab -r -u $UserName)" 

Вот результат:

Commencing user Test2 removal 
chsh: unknown user: Test2 
Deactivating Test2 shell account ... 
groups: Test2: no such user 
Listing group(s) user: 
scripts/sudo.sh: line 332: /delete_Test2/crontab.bak: No such file or directory 
Saving Crontab ... 

Пользователь удалить это Test2, что этот случай «якобы» не существует (другой вопрос для другого времени). Теперь, не следует ли показывать stderr msg рядом с командой или под ней, а не над ней?

Заранее спасибо

ответ

3

Когда оболочка выполняет линию echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)", вот последовательность событий:

  1. Оболочка работает chsh -s /usr/bin/false Test2, с его стандартный вывод происходит в буфер захвата, так что оболочка может использовать его позже.
  2. chsh обнаруживает, что «Test2» не существует и печатает «chsh: unknown user: Test2» в его stderr. Поскольку оболочка не делала ничего особенного со своим stderr, это происходит непосредственно в stderr оболочки, который является вашим терминалом.
  3. chsh выходит
  4. Оболочка принимает захваченное выход (примечание: стандартный вывод, а не Stderr) из chsh (там не было), и заменяет его в echo командной строки, что дает echo -e "Deactivating Test2 shell account ..." ""

Примечание что сообщение об ошибке будет напечатано на шаге 2, но сообщение о том, что должно произойти, не будет напечатано до шага 4.

Существует несколько способов решения этой проблемы; обычно лучше всего избегать всего беспорядка захвата вывода команды, а затем повторять ее. Это бессмысленно и просто приводит к таким путаницам (и некоторым другим, с которыми вы не сталкивались). Просто запустите команду напрямую, и пусть ее выход (как stdout, так и stderr) переместится в их обычные места в обычном порядке.

BTW, я также рекомендую избегать echo -e, или действительно echo -anything. В POSIX standard for echo говорится: «Реализации не должны поддерживать какие-либо варианты». Фактически, некоторые реализации поддерживают варианты; другие просто рассматривают их как часть строки для печати.Кроме того, некоторые интерпретируют escape-последовательности (например, \n) в строках для печати, некоторые - нет, а некоторые только делают, если указан -e (нарушая стандарт POSIX). Учитывая, насколько непредсказуемы эти функции, лучше всего избегать таких ситуаций iffy и вместо этого использовать printf (что более сложно использовать, но гораздо более предсказуемо) или (как в вашем случае) просто используйте отдельную команду echo для каждого линия.

Кроме того, вы должны почти всегда ссылки переменные двойные кавычки (например, groups "$UserName" вместо groups $UserName), только в случае, если они содержат пробелы, символы и т.д.

Основываясь на вышесказанном, вот как я бы написать сценарий:

echo # print a blank line 
echo "Commencing user $UserName removal" 
echo "Deactivating $UserName shell account ..." 
chsh -s /usr/bin/false "$UserName" 

echo "Listing group(s) user: " 
groups "$UserName" 

echo "Removing Crontab ... " 
crontab -r -u "$UserName" 
+0

Спасибо вам всем. Гордон, ты и Игнасио отвечаете на работу; однако то, что я узнал от вас, заключается в том, что я НЕ НУЖДАЮСЬ ЭХО МОЕЙ КОМАНДЕ НА ВСЕХ !!! и убедившись, что на всякий случай нужно поставить UserName. благодаря – user3112318

1

Теперь, не следует ГЗС дисплей STDERR рядом с командой или ниже ее, а не над ним?

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

1

Это потому, что chsh пишет stderr до У bash есть шанс написать в стандартный вывод. Перенаправить поток ошибок на стандартный вывод, чтобы получить это право:

echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName 2>&1)" 

В общем, лучше, чтобы проверить, если пользователь существует, прежде чем пытаться отключить его.