Bash убрать вывод ошибок

How can I suppress error messages for a shell command?

For example, if there are only jpg files in a directory, running ls *.zip gives an error message:

   $ ls *.zip
   ls: cannot access '*.zip': No such file or directory

Is there an option to suppress such error messages? I want to use this command in a Bash script, but I want to hide all errors.

Peter Mortensen's user avatar

asked Sep 3, 2015 at 15:31

Peter's user avatar

6

Most Unix commands, including ls, will write regular output to standard output and error messages to standard error, so you can use Bash redirection to throw away the error messages while leaving the regular output in place:

ls *.zip 2> /dev/null

Peter Mortensen's user avatar

answered Sep 3, 2015 at 15:33

AJefferiss's user avatar

AJefferissAJefferiss

1,5931 gold badge12 silver badges17 bronze badges

1

$ ls *.zip 2>/dev/null

will redirect any error messages on stderr to /dev/null (i.e. you won’t see them)

Note the return value (given by $?) will still reflect that an error occurred.

answered Sep 3, 2015 at 15:34

Brian Agnew's user avatar

Brian AgnewBrian Agnew

267k36 gold badges333 silver badges440 bronze badges

To suppress error messages and also return the exit status zero, append || true. For example:

$ ls *.zip && echo hello
ls: cannot access *.zip: No such file or directory
$ ls *.zip 2>/dev/null && echo hello
$ ls *.zip 2>/dev/null || true && echo hello
hello

$ touch x.zip
$ ls *.zip 2>/dev/null || true && echo hello
x.zip
hello

Peter Mortensen's user avatar

answered Nov 11, 2017 at 6:45

A-C's user avatar

A-CA-C

1211 silver badge4 bronze badges

2

I attempted ls -R [existing file] and got an immediate error.
ls: cannot access ‘existing file’: No such file or directory

So, I used the following:

ls -R 2>dev/null | grep -i [existing file]*

ls -R 2>dev/null | grep -i text*

Or, in your case:

ls -R 2>dev/null | grep -i *.zip

answered Jan 4, 2022 at 19:36

Richard's user avatar

1

My solution with a raspberry pi3 with buster.

ls -R 2>/dev/null | grep -i [existing file]*

2>/dev/null is very usefull with Bash script to avoid useless warnings or errors.

Do not forget slash caracter

answered Feb 6 at 13:32

fr3d mobile's user avatar

1

I’m trying to show the number of lines, words and characters of all configuration files in /etc/*conf (with command wc).

How can I modify the command (or commandline) to not view the error messages?

quack quixote's user avatar

quack quixote

41.9k14 gold badges105 silver badges130 bronze badges

asked Mar 25, 2010 at 22:26

pedro's user avatar

1

wc /etc/*conf 2>/dev/null

answered Mar 25, 2010 at 23:33

Dennis Williamson's user avatar

Dennis WilliamsonDennis Williamson

105k19 gold badges164 silver badges187 bronze badges

i don’t have access to a shell right now, but you can try something like

cat /etc/*.conf 2> /dev/null | wc -l

That should redirect all the errors and leave the output to be passed to wc

answered Mar 25, 2010 at 22:39

Roy Rico's user avatar

Roy RicoRoy Rico

5,8187 gold badges43 silver badges57 bronze badges

1

Usually just redirect the standard output to /dev/null to ignore the output, but this is not good practice when writing shell scripts

Try use -q instead to run the shell in quite mode, which will produce less output.

This might not be relevant to the question, but just FYI.

answered May 1, 2013 at 7:10

imcoddy's user avatar

imcoddyimcoddy

2711 gold badge2 silver badges5 bronze badges

how can one turn off the error messages of a bash script?

I want to turn it off, and handle the expected ones by myself

For instance, when it does not find some files, to show my specific error message.

Thanks

asked Mar 11, 2010 at 20:13

Open the way's user avatar

Open the wayOpen the way

26k50 gold badges142 silver badges196 bronze badges

You don’t want to turn them off — you want to capture them and parse them so you can show your own message. (Though if the script is well-written, you don’t actually have to capture them, just check the exit code.) You’ll need to redirect stderr

script_to_run 2> captured_stderr
# now examine the contents of captured_stderr

If you can do it just with the exit code, you can redirect to /dev/null instead.

For more about redirection, try the short version or long version here.

answered Mar 11, 2010 at 20:19

Cascabel's user avatar

You can put 2>/dev/null behind a command to suppress errors:

ls /home/cas/thisfolderdoesntexist -> error

ls /home/cas/thisfolderdoesntexist 2>/dev/null -> no output because error is suppressed.

You can also put 2>/dev/null behind a script to run the complete script with errors suppressed:

./script.sh 2>/dev/null

What your doing is redirecting (>) errors (2) to /dev/null. Every piece of data (in this case the output of your command(s)/script) that is redirected to /dev/null will be completely ignored. See it as a trash can for data.


Edit:
2>/dev/null suppresses the output of the command, not the complete pipe. In the example that you gave, you’re supressing errors from the awk command. If the error is comming from the ls command, do the following (this will suppress errors from the ls command):

ls /bootpool 2>/dev/null | grep boot | awk 'NR==1{print $1}'

If the error is comming from the grep command:

ls /bootpool | grep boot 2>/dev/null | awk 'NR==1{print $1}'

I think you get it now.

A good thing to remember:

1 = stdout = normal output of a command

2 = stderr = error output of a command

0 = stdin = input to a command (this isn’t usefull for redirecting, more for logging)


I also improved your script (using shellcheck, you can install it or use their online tool link):

#!/bin/sh
boot=$(find /bootpool/*boot* 2>/dev/null | sed "s|/.*/||")
data=$(find /datapool/*boot* 2>/dev/null | sed "s|/.*/||")
echo "boot"
if [ "$boot" = "boot" ] 
then
        echo "boot"
        pass=$(grep rootpw /bootpool/boot/loader.conf | grep -o '".*"' | sed 's|"||g' | awk 'BEGIN { ORS = " " } { print }')

elif [ "$data" = "boot" ]
then
        pass=$(grep rootpw /datapool/boot/loader.conf | grep -o '".*"' | sed 's|"||g' | awk 'BEGIN { ORS = " " } { print }')

else
        echo "Couldn't find boot in bootpool nor datapool"
        exit
fi

if [ "$pass" = edjos ]
then
        echo "You are at default password. kindly change the password"
        oldpass=$(grep root /etc/master.passwd | awk 'NR==1 { print $1 }' | cut -d ':' -f 2 | sed 's/$/%/g')
        passwd
        newpass=$(grep root /etc/master.passwd | awk 'NR==1 { print $1 }' | cut -d ':' -f 2 | sed 's/$/%/g')
        if [ "$newpass" != "$oldpass" ]
        then              
                if [ "$boot" = "boot" ]
                then 
                        sed -i.bak '/mfsbsd.rootpw/s/edjos//' /bootpool/boot/loader.conf
                        sed -i.bak '/mfsbsd.rootpwhash/d' /bootpool/boot/loader.conf
                        echo "mfsbsd.rootpwhash="$newpass""  >> /bootpool/boot/loader.conf
                        echo "Great! password updated successfully"

                elif [ "$data" = "boot" ]
                then
                        sed -i.bak '/mfsbsd.rootpw/s/edjos//' /datapool/boot/loader.conf
                        sed -i.bak '/mfsbsd.rootpwhash/d' /datapool/boot/loader.conf
                        echo "mfsbsd.rootpwhash="$newpass""  >> /datapool/boot/loader.conf
                        echo "Great! password updated successfully"
                fi
        fi
else
        echo "Great! you are having authorised password"
fi
  1. You were using == but /bin/sh doesn’t make use of that. Only =. When you use /bin/bash, == will actually become usefull. But as you don’t, you need to use =.
  2. I changed the way you set the boot and data variables. The way you did it was inefficient.
  3. When both $boot and $data are empty, the script will catch it instead of letting you continue. This is handy because in your second if statement, when $oldpass and $newpass aren’t equal, it depends on either $boot or $data to contain «boot». But what if they don’t? That’s what the else is for in the first if-statement.
  4. Putting "" around variables. echo $var -> echo "$var"

How can I suppress error messages for a shell command?

For example, if there are only jpg files in a directory, running ls *.zip gives an error message:

   $ ls *.zip
   ls: cannot access '*.zip': No such file or directory

Is there an option to suppress such error messages? I want to use this command in a Bash script, but I want to hide all errors.

Peter Mortensen's user avatar

asked Sep 3, 2015 at 15:31

Peter's user avatar

6

Most Unix commands, including ls, will write regular output to standard output and error messages to standard error, so you can use Bash redirection to throw away the error messages while leaving the regular output in place:

ls *.zip 2> /dev/null

Peter Mortensen's user avatar

answered Sep 3, 2015 at 15:33

AJefferiss's user avatar

AJefferissAJefferiss

1,5631 gold badge12 silver badges17 bronze badges

1

$ ls *.zip 2>/dev/null

will redirect any error messages on stderr to /dev/null (i.e. you won’t see them)

Note the return value (given by $?) will still reflect that an error occurred.

answered Sep 3, 2015 at 15:34

Brian Agnew's user avatar

Brian AgnewBrian Agnew

266k36 gold badges331 silver badges438 bronze badges

To suppress error messages and also return the exit status zero, append || true. For example:

$ ls *.zip && echo hello
ls: cannot access *.zip: No such file or directory
$ ls *.zip 2>/dev/null && echo hello
$ ls *.zip 2>/dev/null || true && echo hello
hello

$ touch x.zip
$ ls *.zip 2>/dev/null || true && echo hello
x.zip
hello

Peter Mortensen's user avatar

answered Nov 11, 2017 at 6:45

A-C's user avatar

A-CA-C

1211 silver badge4 bronze badges

2

I attempted ls -R [existing file] and got an immediate error.
ls: cannot access ‘existing file’: No such file or directory

So, I used the following:

ls -R 2>dev/null | grep -i [existing file]*

ls -R 2>dev/null | grep -i text*

Or, in your case:

ls -R 2>dev/null | grep -i *.zip

answered Jan 4, 2022 at 19:36

Richard's user avatar

1

Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит

В прошлый раз, в третьей части этой серии материалов по bash-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.

image

Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:

  • Отображение выводимых данных на экране.
  • Перенаправление вывода в файл.

Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться с тем, как в Linux обрабатывается ввод и вывод, а значит — научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов.

Стандартные дескрипторы файлов

Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.

Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.

  • 0, STDIN — стандартный поток ввода.
  • 1, STDOUT — стандартный поток вывода.
  • 2, STDERR — стандартный поток ошибок.

Эти три специальных дескриптора обрабатывают ввод и вывод данных в сценарии.
Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них.

STDIN

STDIN — это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда в сценариях используют символ перенаправления ввода — <, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.

Многие команды bash принимают ввод из STDIN, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat.

Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN. После того, как вы вводите очередную строку, cat просто выводит её на экран.

STDOUT

STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT, что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >>.

Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:

pwd >> myfile

То, что выведет pwd, будет добавлено к файлу myfile, при этом уже имеющиеся в нём данные никуда не денутся.

Перенаправление вывода команды в файл

Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу xfile, задумывая всё это для того, чтобы в файл myfile попало сообщение об ошибке.

ls –l xfile > myfile

После выполнения этой команды мы увидим сообщения об ошибках на экране.

Попытка обращения к несуществующему файлу

При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост — воспользоваться третьим стандартным дескриптором.

STDERR

STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT, именно поэтому при возникновении ошибки мы видим сообщение на экране.

Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.

▍Перенаправление потока ошибок

Как вы уже знаете, дескриптор файла STDERR — 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:

ls -l xfile 2>myfile
cat ./myfile

Сообщение об ошибке теперь попадёт в файл myfile.

Перенаправление сообщения об ошибке в файл

▍Перенаправление потоков ошибок и вывода

При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:

ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent

Перенаправление ошибок и стандартного вывода

Оболочка перенаправит то, что команда ls обычно отправляет в STDOUT, в файл correctcontent благодаря конструкции 1>. Сообщения об ошибках, которые попали бы в STDERR, оказываются в файле errorcontent из-за команды перенаправления 2>.

Если надо, и STDERR, и STDOUT можно перенаправить в один и тот же файл, воспользовавшись командой &>:

Перенаправление STDERR и STDOUT в один и тот же файл

После выполнения команды то, что предназначено для STDERR и STDOUT, оказывается в файле content.

Перенаправление вывода в скриптах

Существует два метода перенаправления вывода в сценариях командной строки:

  • Временное перенаправление, или перенаправление вывода одной строки.
  • Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.

▍Временное перенаправление вывода

В скрипте можно перенаправить вывод отдельной строки в STDERR. Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR, при этом перед номером дескриптора надо поставить символ амперсанда (&):

#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"

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

Временное перенаправление

Запустим скрипт так, чтобы вывод STDERR попадал в файл.

./myscript 2> myfile

Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.

Сообщения об ошибках записываются в файл

▍Постоянное перенаправление вывода

Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec:

#!/bin/bash
exec 1>outfile
echo "This is a test of redirecting all output"
echo "from a shell script to another file."
echo "without having to redirect every line"

Запустим скрипт.

Перенаправление всего вывода в файл

Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo, попало в этот файл.

Команду exec можно использовать не только в начале скрипта, но и в других местах:

#!/bin/bash
exec 2>myerror
echo "This is the start of the script"
echo "now redirecting all output to another location"
exec 1>myfile
echo "This should go to the myfile file"
echo "and this should go to the myerror file" >&2

Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.

Перенаправление вывода в разные файлы

Сначала команда exec задаёт перенаправление вывода из STDERR в файл myerror. Затем вывод нескольких команд echo отправляется в STDOUT и выводится на экран. После этого команда exec задаёт отправку того, что попадает в STDOUT, в файл myfile, и, наконец, мы пользуемся командой перенаправления в STDERR в команде echo, что приводит к записи соответствующей строки в файл myerror.

Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.

Перенаправление ввода в скриптах

Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:

exec 0< myfile

Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл myfile, а не обычный STDIN. Посмотрим на перенаправление ввода в действии:

#!/bin/bash
exec 0< testfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done

Вот что появится на экране после запуска скрипта.

Перенаправление ввода

В одном из предыдущих материалов вы узнали о том, как использовать команду read для чтения данных, вводимых пользователем с клавиатуры. Если перенаправить ввод, сделав источником данных файл, то команда read, при попытке прочитать данные из STDIN, будет читать их из файла, а не с клавиатуры.

Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.

Создание собственного перенаправления вывода

Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.

Назначить дескриптор для вывода данных можно, используя команду exec:

#!/bin/bash
exec 3>myfile
echo "This should display on the screen"
echo "and this should be stored in the file" >&3
echo "And this should be back on the screen"

После запуска скрипта часть вывода попадёт на экран, часть — в файл с дескриптором 3.

Перенаправление вывода, используя собственный дескриптор

Создание дескрипторов файлов для ввода данных

Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN в другом дескрипторе, прежде чем перенаправлять ввод данных.

После окончания чтения файла можно восстановить STDIN и пользоваться им как обычно:

#!/bin/bash
exec 6<&0
exec 0< myfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
exec 0<&6
read -p "Are you done now? " answer
case $answer in
y) echo "Goodbye";;
n) echo "Sorry, this is the end.";;
esac

Испытаем сценарий.

Перенаправление ввода

В этом примере дескриптор файла 6 использовался для хранения ссылки на STDIN. Затем было сделано перенаправление ввода, источником данных для STDIN стал файл. После этого входные данные для команды read поступали из перенаправленного STDIN, то есть из файла.

После чтения файла мы возвращаем STDIN в исходное состояние, перенаправляя его в дескриптор 6. Теперь, для того, чтобы проверить, что всё работает правильно, скрипт задаёт пользователю вопрос, ожидает ввода с клавиатуры и обрабатывает то, что введено.

Закрытие дескрипторов файлов

Оболочка автоматически закрывает дескрипторы файлов после завершения работы скрипта. Однако, в некоторых случаях нужно закрывать дескрипторы вручную, до того, как скрипт закончит работу. Для того, чтобы закрыть дескриптор, его нужно перенаправить в &-. Выглядит это так:

#!/bin/bash
exec 3> myfile
echo "This is a test line of data" >&3
exec 3>&-
echo "This won't work" >&3

После исполнения скрипта мы получим сообщение об ошибке.

Попытка обращения к закрытому дескриптору файла

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

Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.

Получение сведений об открытых дескрипторах

Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой lsof. Во многих дистрибутивах, вроде Fedora, утилита lsof находится в /usr/sbin. Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.

У этой команды есть множество ключей, рассмотрим самые важные.

  • -p Позволяет указать ID процесса.
  • -d Позволяет указать номер дескриптора, о котором надо получить сведения.

Для того, чтобы узнать PID текущего процесса, можно использовать специальную переменную окружения $$, в которую оболочка записывает текущий PID.

Ключ -a используется для выполнения операции логического И над результатами, возвращёнными благодаря использованию двух других ключей:

lsof -a -p $$ -d 0,1,2

Вывод сведений об открытых дескрипторах

Тип файлов, связанных с STDIN, STDOUT и STDERR — CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.

Посмотрим на вызов команды lsof из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:

#!/bin/bash
exec 3> myfile1
exec 6> myfile2
exec 7< myfile3
lsof -a -p $$ -d 0,1,2,3,6,7

Вот что получится, если этот скрипт запустить.

Просмотр дескрипторов файлов, открытых скриптом

Скрипт открыл два дескриптора для вывода (3 и 6) и один — для ввода (7). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.

Подавление вывода

Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null. Это — что-то вроде «чёрной дыры».

Вот, например, как подавить вывод сообщений об ошибках:

ls -al badfile anotherfile 2> /dev/null

Тот же подход используется, если, например, надо очистить файл, не удаляя его:

cat /dev/null > myfile

Итоги

Сегодня вы узнали о том, как в сценариях командной строки работают ввод и вывод. Теперь вы умеете обращаться с дескрипторами файлов, создавать, просматривать и закрывать их, знаете о перенаправлении потоков ввода, вывода и ошибок. Всё это очень важно в деле разработки bash-скриптов.

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

Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так — передаём слово вам.

8.4.2. Подавление вывода сообщений об ошибках

Допустим, вы хотите найти запись пользователя louise в системном файле паролей:

$ grep louise /etc/passwd

louise:lxAL6GW9G.ZyY:501:501:Accounts Sect1С:/home/accts/louise:/bin/sh

He исключена возможность, что вы забудете, как называется этот файл. В таком случае воспользуйтесь следующей командой:

$ grep louise /etc/password

grep: /etc/password: No such file or directory

Команда grep выводит сообщение об ошибке, в которой говорится о том, что указанного файла не существует. Можно попробовать провести поиск во всех файлах каталога /etc:

$ grep louise /etc/*

Однако в результате будут выведены многочисленные сообщения об ошибках, гласящие, что к определенным файлам доступ запрещен, а некоторые элементы каталога являются подкаталогами и поиск в них не ведется.

В подобной ситуации можно воспользоваться опцией -s, которая подавляет вывод сообщений об ошибках:

$ grep -a louise /etc/*

Если ваша версия команды grep не поддерживает данную опцию, воспользуйтесь следующей командой:

$ grep louise /etc/* 2> /dev/null

Эта команда направляет поток ошибок (2>) в системную корзину (устройство /dev/null). На жаргоне системных администраторов это устройство называется битодробилкой.

Читайте также

Уровни вывода сообщений ядра

Уровни вывода сообщений ядра
Главное отличие между функциями printk() и printf() — это возможность в первой указывать уровень вывода сообщений ядра (loglevel). Ядро использует уровень вывода сообщений для принятия решения о том, выводить сообщение на консоль или нет. Ядро выводит на

Отправка сообщений об ошибках

Отправка сообщений об ошибках
Если вы обнаружили ошибку, то наилучшим решением будет исправить ее, сгенерировать соответствующую заплату, оттестировать и отправить, как это будет рассказано в следующих разделах. Конечно, можно и просто сообщить об ошибке, чтобы

7.2 Сообщения об ошибках ICMP

7.2 Сообщения об ошибках ICMP
Бывают ситуации, приводящие к отбрасыванию (удалению из сети) датаграммы IP. Например, точка назначения может стать недоступной из-за обрыва связи. Или может завершиться время жизни датаграммы. Маршрутизатор не сможет переслать длинную

7.2.1 Типы сообщений об ошибках

7.2.1 Типы сообщений об ошибках
На рис. 7.3 показаны обобщенные сообщения, формируемые маршрутизатором и хостом назначения для отчета о возникшей проблеме. В таблице 7.1 перечислены формальные имена сообщений об ошибках ICMP.

Рис. 7.3. Типы сообщений об ошибках ICMPТаблица 7.1

Подавление линий заднего плана

Подавление линий заднего плана

Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту

В.З. Стандартные функции вывода сообщений об ошибках

В.З. Стандартные функции вывода сообщений об ошибках
Мы определили свой набор функций, используемых во всех программах книги для обработки ситуаций с возникновением ошибок. Причина, по которой мы создаем эти функции, заключается в том, что теперь мы можем писать команды в

Отчет об ошибках

Отчет об ошибках
На вкладке Дополнительно в окне Свойства системы нажимаем кнопку Отчет об ошибках. Откроется одноименное окно Отчет об ошибках (рис. 4.5), в котором устанавливаем переключатель в положение Отключить отчет об ошибках и оставляем установленным флажок Но

Получение и пересылка сообщений. Создание ответных сообщений

Получение и пересылка сообщений. Создание ответных сообщений
Чтобы получить новую почту, выполните команду главного меню Сервис ? Отправить/Получить ? Доставить почту либо нажмите клавишу F9. Все полученные почтовые сообщения будут помещены в папку Входящие и помечены

Шаг 20 — Временные объекты. Неявные вызовы конструкторов и их подавление.

Шаг 20 — Временные объекты. Неявные вызовы конструкторов и их подавление.
Не удается углубиться в какую-либо тему. Приходится касаться по верхам, потом переключаться на что-то другое. С другой стороны, может это и правильно, часто достаточно только знать, что есть ТАКОЕ

Настройка вывода сообщений об ошибках с помощью ‹customErrors›

Настройка вывода сообщений об ошибках с помощью ‹customErrors›
Элемент ‹customErrors› может использоваться для автоматического перенаправления всех ошибок в пользовательский набор файлов *.htm. Это может оказаться полезным тогда, когда вы хотите построить более понятную для

Подавление линий заднего плана

Подавление линий заднего плана

Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту

Сообщение об ошибках gbak

Сообщение об ошибках gbak
В табл. 38.3 описаны сообщения об ошибках, которые могут возникнуть в процессе копирования и восстановления, вместе с некоторыми советами, как поступать с этими ошибками.Таблица 38.3. Сообщения об ошибках gbak при копировании и восстановлении

Сообщение

Подавление линий заднего плана

Подавление линий заднего плана

Команда HIDE обеспечивает создание рисунка без скрытых линий . Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту

Подавление линий заднего плана

Подавление линий заднего плана

Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту

Отчеты об ошибках

Отчеты об ошибках
В операционной системе Windows Vista реализован новый механизм отчетов об ошибках. Теперь ограничить и настроить его работу можно с помощью следующих параметров, расположенных в ветви реестра HKEY_CURRENT_USERSoftwarePoliciesMicrosoftWindowsWindows Error Reporting. Если не сказано иное,


0

2

Всех приветствую, нужна помощь с скриптом.
ОС Alt Linux Рабочая станция
Linux host-15tstalt 5.10.128-std-def-alt1 #1 SMP Fri Jul 8 14:39:36 UTC 2022 x86_64 GNU/Linux
Имеется скрипт с таким содержимым.

#! /bin/bash
source /media/dirlab/coutlistuser
find /media/dirlab -user $43 -exec sh -c "file '{}' | grep -q 'ELF'" ; -print | wc -l

Файл /media/dirlab/coutlistuser это автоматически генерируемый файл с содержимым по пользователям. Нужен для того что бы проверять появились пользователи новые или нет.
Выглядит примерно так

p1=polkitd	
p2=_avahi	
p3=_ldm	
p4=_chrony	
.....	
p49=mxvel	
p50=ivanov	
p51=petrov	
p52=sidorov	
p53=pupkin 

find /media/dirlab — поиск в нужном нам каталоге
-user $43 -exec sh -c «file ‘{}’ | grep -q ‘ELF’» ; -print — условие при котором происходит поиск исполняемых ELF файлов по владельцам. Источник с пользователями как раз для этого.
-print | wc -l — вывод численного количества ELF файлов.

Возникает несколько ошибок/задач которые не знаю как исправить.

  1. Если переменная с пользователями ($p54 и больше) превышает количество существующих пользователей в системе появляется ошибка
find: ‘-exec’ is not the name of a known user

Понятно почему появляется, но нужно что бы информация о несуществующем пользователе не выводилась.

  1. Если пользователь существует но нет файлов ELF в каталоге скрипт указывает количество файлов

Это пустое количество тоже выводить не нужно.

Пробовал обернуть это в значения «если то»

#!/bin/bash
source /media/dirlab/coutlistuser

if
 COUNT=`find /media/dirlab -user $p51 -exec sh -c "file '{}' | grep -q 'ELF'" ; -print | wc -l `
then [ $COUNT -eq 0 ]
else 
echo "$p51 $COUNT"
fi

Но вывод информации вообще перестает происходить даже если ELF файлы есть.

Кто знает как сделать 1 и 2 пункт?

Каждый раз, когда мы запускаем команду Bash на нашем терминале Linux Mint 20, обычно мы видим какой-то вывод на терминале. То же самое для команд и сценариев Bash. Иногда мы можем не желать видеть такой результат. Это происходит особенно, когда мы хотим отладить программу и заинтересованы только в обнаружении возникающих ошибок. В этой ситуации, если нам будет представлен весь вывод, он будет не только бесполезен для нас, но и будет тратить наше время на поиск реальной проблемы.

Вот почему мы предпочитаем подавлять фактический вывод команд или скриптов Bash таким образом, чтобы на терминале отображались только их ошибки (если таковые имеются). В противном случае ничего не будет отображаться. Поэтому сегодня мы поговорим о методе подавления всего вывода команды Bash в Linux Mint 20.

Метод подавления всего вывода команды Bash в Linux Mint 20:

Чтобы объяснить вам метод подавления всего вывода команды Bash в Linux Mint 20, мы хотели бы поделиться с вами некоторыми примерами.

Мы создали простой сценарий Bash, в котором мы просто печатаем случайное сообщение на терминале. Мы будем использовать этот сценарий Bash в Примере №1 и Примере №2. Этот сценарий Bash отображается на прикрепленном изображении. Мы назвали наш файл Bash Suppress.sh.

Сценарий Bash, который мы только что создали, можно просто запустить с помощью команды «bash». Прежде чем подавлять вывод команды «bash», мы сначала хотели бы показать вам ее фактический вывод. Для этого вам нужно выполнить свой сценарий Bash следующим образом:

$ трепать Suppress.sh


Выполнение этого сценария Bash просто отобразит наше фиктивное сообщение на терминале, как показано ниже:

Теперь, чтобы подавить вывод команды «bash», мы запустим следующую команду в нашем терминале:

$ трепать Suppress.sh >/разработчик/значение NULL


Выполнение процитированной выше команды отправит весь вывод в корзину> / dev / null, и, следовательно, на вашем терминале ничего не будет отображаться, как показано на добавленном ниже изображении:

Пример №2: Подавление вывода команды «cat»:

Мы также можем отобразить содержимое нашего файла сценария Bash на терминале с помощью команды «cat». Прежде чем подавлять вывод команды «cat», мы сначала хотели бы показать вам ее фактический вывод. Для этого вам нужно запустить команду «cat» следующим образом:

$ Кот Suppress.sh


Выполнение команды «cat» просто отобразит содержимое нашего файла сценария Bash на терминале, как показано ниже:

Теперь, чтобы подавить вывод команды «cat», мы запустим следующую команду в нашем терминале:

$ Кот Suppress.sh >/разработчик/значение NULL


При выполнении указанной выше команды весь вывод будет отправлен в корзину> / dev / null, и, следовательно, на вашем терминале ничего не будет отображаться, как показано на изображении ниже:

Пример №3: Подавление вывода команды «–help»:

Если вы хотите узнать подробности использования какой-либо команды или пакета в Linux Mint 20, вы можете использовать команду «–help». Прежде чем подавлять вывод команды «–help», мы сначала хотели бы показать вам ее фактический вывод. Для этого вам нужно запустить команду «–help» следующим образом:

$ нано—помощь


Мы хотели получить доступ к справочному руководству редактора nano, которое показано на изображении ниже:

Теперь, чтобы подавить вывод команды «–help», мы запустим следующую команду в нашем терминале:

$ нано—помощь>/разработчик/значение NULL


При выполнении указанной выше команды весь вывод будет отправлен в корзину> / dev / null, и, следовательно, на вашем терминале ничего не будет отображаться, как показано на изображении, добавленном ниже:

Пример №4: Подавление вывода команды «–версия»:

Если вы хотите проверить версию любого установленного пакета или команды в Linux Mint 20, вы можете использовать команду «–version». Прежде чем подавлять вывод команды «–version», мы сначала хотели бы показать вам ее фактический вывод. Для этого вам нужно запустить команду «–версия» следующим образом:

$ нано—версия


Мы хотели проверить версию редактора nano, которая показана на изображении ниже:

Теперь, чтобы подавить вывод команды «–version», мы запустим следующую команду в нашем терминале:

$ нано—версия>/разработчик/значение NULL


При выполнении указанной выше команды весь вывод будет отправлен в корзину> / dev / null, и, следовательно, на вашем терминале ничего не будет отображаться, как показано на изображении, добавленном ниже:

Пример № 5: Подавление вывода команды «man»:

Когда бы вы ни захотели прочитать руководство или справочные страницы любой установленной команды или пакета в Linux Mint 20, вы можете использовать команду «man». Прежде чем подавлять вывод команды «man», мы сначала хотели бы показать вам ее фактический вывод. Для этого вам нужно запустить команду «man» следующим образом:

$ человекнано


Мы хотели получить доступ к руководству редактора nano, которое показано на изображении ниже:

Теперь, чтобы подавить вывод команды «man», мы запустим следующую команду в нашем терминале:

$ человекнано>/разработчик/значение NULL


При выполнении указанной выше команды весь вывод будет отправлен в корзину> / dev / null, и, следовательно, на вашем терминале ничего не будет отображаться, как показано на изображении ниже:

Вывод:

В этой статье мы поделились с вами пятью различными примерами подавления всего вывода команды Bash в Linux Mint 20. Пройдя эти примеры, теперь вы легко сможете подавить вывод любой желаемой команды Bash или сценария Bash при использовании Linux Mint 20.

Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов. Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.

  • 0, STDIN — стандартный поток ввода
  • 1, STDOUT — стандартный поток вывода
  • 2, STDERR — стандартный поток ошибок

STDIN

STDIN — это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда используется символ перенаправления ввода — <, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.

Многие команды bash принимают ввод из STDIN, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat.

Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN. После того, как вы вводите очередную строку, cat просто выводит её на экран. И останавливается после того как получает EOF. EOF вводится нажатием сочетания клавиш Ctrl+D.

STDOUT

STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT, что приводит к их появлению в консоли. Данные можно перенаправить в файл, для этого используется символ перенаправления вывода >.

Можно осуществить перенаправление вывода в файл с добавлением в конец с помощью >>. При этом информация, хранящаяся в файле не будет удалена, а вся новая информация будет добавлена в конец этого файла.

STDERR

STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT, именно поэтому при возникновении ошибки мы видим сообщение на экране.

Рассмотрим простой пример — нужно записать в файл data.txt содержимое директории data. Если директория не существует, сообщение об ошибке надо записать в файл error.txt. Чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:

$ ls data 1> data.txt 2> error.txt

Если надо, STDERR и STDOUT можно перенаправить в один и тот же файл, воспользовавшись &>:

$ ls data &> data-error.txt

Устаревшая форма записи:

$ ls data > data-error.txt 2>&1

Оболочка определяет порядок перенаправления потоков в командной строке слева направо, поэтому приведенный выше пример нельзя записать так:

$ ls data 2>&1 > data-error.txt

В этом случае сначала вывод ошибок перенаправляется в стандартный вывод (на экран), а потом стандартный вывод перенаправляется в файл data-error.txt. То есть, ошибки будут выведены в консоль, а данные — в файл.

Для дозаписи в файл data-error.txt

$ ls data &>> data-error.txt

Перенаправление вывода в скриптах

Существует два метода перенаправления вывода в сценариях командной строки:

  • Временное перенаправление, или перенаправление вывода одной строки
  • Постоянное перенаправление, или перенаправление всего вывода сценария

Временное перенаправление вывода

В сценарии можно перенаправить вывод отдельной строки в STDERR. Чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR, при этом перед номером дескриптора надо поставить символ амперсанда:

#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"

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

$ ./test.sh
This is an error
This is normal output

Запустим скрипт так, чтобы вывод STDERR попадал в файл:

$ ./test.sh 2> error.txt
This is normal output
$ cat error.txt
This is an error

Теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл error.txt.

Постоянное перенаправление вывода

Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять >&2 к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec:

#!/bin/bash
exec 1> output.txt
echo "Это пример перенаправления всего"
echo "вывода сценария в файл output.txt"
echo "без перенаправления каждой строки"

После запуска сценария весь вывод будет перенаправлен в файл output.txt.

Команду exec можно использовать не только в начале скрипта, но и в других местах:

#!/bin/bash

# ошибки перенаправляем в файл error.txt
exec 2> error.txt
# строка будет выведена на экран
echo "Первый вывод сценария"
# перенаправляем вывод в файл output.txt
exec 1> output.txt
# строка будет записана в файл output.txt
echo "Второй вывод сценария"
# строка будет записана в файл error.txt
echo "Третий вывод сценария" >&2

Перенаправление ввода в скриптах

Для перенаправления ввода можно воспользоваться тем же способом, который использовался для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:

$ exec 0< data.txt

Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл data.txt, а не обычный STDIN. Посмотрим на перенаправление ввода в действии:

#!/bin/bash
exec 0< data.txt
count=1
while read line ; do
    echo "Line #$count: $line"
    count=$(( $count + 1 ))
done

Подавление вывода

Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null.

Вот, например, как подавить вывод сообщений об ошибках:

$ ls -al badfile.txt file.txt 2> /dev/null

Тот же подход используется, если, например, надо очистить файл, не удаляя его:

$ cat /dev/null > data.txt

Поиск:
Bash • CLI • Linux • stderr • stdin • stdout • Поток


У меня есть скрипт Bash, который запускает программу с параметрами. Эта программа выводит некоторый статус (делает это, делает это …). Эта программа не может быть тихой. Как я могу предотвратить отображение сценарием чего-либо?

Я ищу что-то похожее на Windows » echo off» .

Ответы:


Следующее посылает стандартный вывод на нулевое устройство (битовая корзина).

scriptname >/dev/null

И если вы также хотите, чтобы сообщения об ошибках отправлялись туда, используйте одно из (первое может работать не во всех оболочках):

scriptname &>/dev/null
scriptname >/dev/null 2>&1
scriptname >/dev/null 2>/dev/null

И, если вы хотите записать сообщения, но не видите их, замените /dev/nullих реальным файлом, таким как:

scriptname &>scriptname.out

Для полноты, в Windows cmd.exe (где «nul» является эквивалентом «/ dev / null»), это:

scriptname >nul 2>nul





Что-то вроде

script > /dev/null 2>&1

Это предотвратит стандартный вывод и вывод ошибок, перенаправляя их обоих /dev/null.





Пытаться

: $(yourcommand)

: это сокращение от «ничего не делать».

$() это просто ваша команда.





Альтернативой, которая может подходить в некоторых ситуациях, является присвоение результата команды переменной:

$ DUMMY=$( grep root /etc/passwd 2>&1 )
$ echo $?
0
$ DUMMY=$( grep r00t /etc/passwd 2>&1 )
$ echo $?
1

Поскольку Bash и другие интерпретаторы командной строки POSIX не рассматривают присвоение переменных как команду, код возврата настоящей команды соблюдается.

Примечание: присвоение с ключевым словом typesetor declareрассматривается как команда, поэтому в качестве оценочного кода возврата в данном случае используется само присвоение, а не команда, выполняемая в вложенной оболочке:

$ declare DUMMY=$( grep r00t /etc/passwd 2>&1 )
$ echo $?
0

Как и в посте andynormancx , используйте это (если вы работаете в среде Unix):

scriptname > /dev/null

Или вы можете использовать это (если вы работаете в среде Windows):

scriptname > nul





Взгляните на этот пример из Проекта документации Linux :

3.6 Пример: файл stderr и stdout 2

Это поместит каждый вывод программы в файл. Иногда это подходит для записей cron, если вы хотите, чтобы команда передавалась в абсолютном молчании.

     rm -f $(find / -name core) &> /dev/null 

Тем не менее, вы можете использовать это простое перенаправление:

/path/to/command &>/dev/null

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

some_code 2>>/dev/null

Или вы также можете попробовать

some_code >>/dev/null



Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:

  • Отображение выводимых данных на экране.
  • Перенаправление вывода в файл.

Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться с тем, как в Linux обрабатывается ввод и вывод, а значит — научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов.

Содержимое

  • 1 Стандартные дескрипторы файлов
  • 2 STDIN
  • 3 STDOUT
  • 4 STDERR
    • 4.1 ▍Перенаправление потока ошибок
    • 4.2 ▍Перенаправление потоков ошибок и вывода
  • 5 Перенаправление вывода в скриптах
    • 5.1 ▍Временное перенаправление вывода
    • 5.2 ▍Постоянное перенаправление вывода
  • 6 Перенаправление ввода в скриптах
  • 7 Создание собственного перенаправления вывода
  • 8 Создание дескрипторов файлов для ввода данных
  • 9 Закрытие дескрипторов файлов
  • 10 Получение сведений об открытых дескрипторах
  • 11 Подавление вывода

Стандартные дескрипторы файлов

Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.

Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.

  • STDIN — стандартный поток ввода.
  • 1STDOUT — стандартный поток вывода.
  • 2STDERR — стандартный поток ошибок.

Эти три специальных дескриптора обрабатывают ввод и вывод данных в сценарии.
Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них.

STDIN

STDIN — это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда в сценариях используют символ перенаправления ввода —  <, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.

Многие команды bash принимают ввод из  STDIN, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды  cat.

Когда вы вводите команду  cat в командной строке, не задавая параметров, она принимает ввод из  STDIN. После того, как вы вводите очередную строку,  cat просто выводит её на экран.

STDOUT

STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в  STDOUT, что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда  >>.

Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:

То, что выведет  pwd, будет добавлено к файлу  myfile, при этом уже имеющиеся в нём данные никуда не денутся.

Перенаправление вывода команды в файл

Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу  xfile, задумывая всё это для того, чтобы в файл  myfile попало сообщение об ошибке.

После выполнения этой команды мы увидим сообщения об ошибках на экране.

Попытка обращения к несуществующему файлу

При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост — воспользоваться третьим стандартным дескриптором.

STDERR

STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает  STDOUT, именно поэтому при возникновении ошибки мы видим сообщение на экране.

Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.

▍Перенаправление потока ошибок

Как вы уже знаете, дескриптор файла  STDERR — 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:

ls l xfile 2>myfile

cat ./myfile

Сообщение об ошибке теперь попадёт в файл  myfile.

Перенаправление сообщения об ошибке в файл

▍Перенаправление потоков ошибок и вывода

При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:

ls l myfile xfile anotherfile 2> errorcontent 1> correctcontent

Перенаправление ошибок и стандартного вывода

Оболочка перенаправит то, что команда  ls обычно отправляет в  STDOUT, в файл  correctcontent благодаря конструкции  1>. Сообщения об ошибках, которые попали бы в  STDERR, оказываются в файле  errorcontent из-за команды перенаправления  2>.

Если надо, и  STDERR, и  STDOUT можно перенаправить в один и тот же файл, воспользовавшись командой  &>:

Перенаправление STDERR и STDOUT в один и тот же файл

После выполнения команды то, что предназначено для  STDERR и  STDOUT, оказывается в файле  content.

Перенаправление вывода в скриптах

Существует два метода перенаправления вывода в сценариях командной строки:

  • Временное перенаправление, или перенаправление вывода одной строки.
  • Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.

▍Временное перенаправление вывода

В скрипте можно перенаправить вывод отдельной строки в  STDERR. Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор  STDERR, при этом перед номером дескриптора надо поставить символ амперсанда ( &):

#!/bin/bash

echo «This is an error» >&2

echo «This is normal output»

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

Временное перенаправление

Запустим скрипт так, чтобы вывод  STDERR попадал в файл.

Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.

Сообщения об ошибках записываются в файл

▍Постоянное перенаправление вывода

Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову  echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой  exec:

#!/bin/bash

exec 1>outfile

echo «This is a test of redirecting all output»

echo «from a shell script to another file.»

echo «without having to redirect every line»

Запустим скрипт.

Перенаправление всего вывода в файл

Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами  echo, попало в этот файл.

Команду  exec можно использовать не только в начале скрипта, но и в других местах:

#!/bin/bash

exec 2>myerror

echo «This is the start of the script»

echo «now redirecting all output to another location»

exec 1>myfile

echo «This should go to the myfile file»

echo «and this should go to the myerror file» >&2

Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.

Перенаправление вывода в разные файлы

Сначала команда  exec задаёт перенаправление вывода из  STDERR в файл  myerror. Затем вывод нескольких команд  echo отправляется в  STDOUT и выводится на экран. После этого команда  exec задаёт отправку того, что попадает в  STDOUT, в файл  myfile, и, наконец, мы пользуемся командой перенаправления в  STDERR в команде  echo, что приводит к записи соответствующей строки в файл  myerror.

Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.

Перенаправление ввода в скриптах

Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда  exec позволяет сделать источником данных для  STDIN какой-нибудь файл:

Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл  myfile, а не обычный  STDIN. Посмотрим на перенаправление ввода в действии:

#!/bin/bash

exec 0< testfile

count=1

while read line

do

echo «Line #$count: $line»

count=$(( $count + 1 ))

done

Вот что появится на экране после запуска скрипта.

Перенаправление ввода

В одном из предыдущих материалов вы узнали о том, как использовать команду  read для чтения данных, вводимых пользователем с клавиатуры. Если перенаправить ввод, сделав источником данных файл, то команда  read, при попытке прочитать данные из  STDIN, будет читать их из файла, а не с клавиатуры.

Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.

Создание собственного перенаправления вывода

Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.

Назначить дескриптор для вывода данных можно, используя команду  exec:

#!/bin/bash

exec 3>myfile

echo «This should display on the screen»

echo «and this should be stored in the file» >&3

echo «And this should be back on the screen»

После запуска скрипта часть вывода попадёт на экран, часть — в файл с дескриптором  3.

Перенаправление вывода, используя собственный дескриптор

Создание дескрипторов файлов для ввода данных

Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните  STDIN в другом дескрипторе, прежде чем перенаправлять ввод данных.

После окончания чтения файла можно восстановить  STDIN и пользоваться им как обычно:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#!/bin/bash

exec 6<&0

exec 0< myfile

count=1

while read line

do

echo «Line #$count: $line»

count=$(( $count + 1 ))

done

exec 0<&6

read p «Are you done now? « answer

case $answer in

y) echo «Goodbye»;;

n) echo «Sorry, this is the end.»;;

esac

Испытаем сценарий.

Перенаправление ввода

В этом примере дескриптор файла 6 использовался для хранения ссылки на  STDIN. Затем было сделано перенаправление ввода, источником данных для  STDIN стал файл. После этого входные данные для команды  read поступали из перенаправленного  STDIN, то есть из файла.

После чтения файла мы возвращаем  STDIN в исходное состояние, перенаправляя его в дескриптор  6. Теперь, для того, чтобы проверить, что всё работает правильно, скрипт задаёт пользователю вопрос, ожидает ввода с клавиатуры и обрабатывает то, что введено.

Закрытие дескрипторов файлов

Оболочка автоматически закрывает дескрипторы файлов после завершения работы скрипта. Однако, в некоторых случаях нужно закрывать дескрипторы вручную, до того, как скрипт закончит работу. Для того, чтобы закрыть дескриптор, его нужно перенаправить в  &. Выглядит это так:

#!/bin/bash

exec 3> myfile

echo «This is a test line of data» >&3

exec 3>&

echo «This won’t work» >&3

После исполнения скрипта мы получим сообщение об ошибке.

Попытка обращения к закрытому дескриптору файла

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

Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.

Получение сведений об открытых дескрипторах

Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой  lsof. Во многих дистрибутивах, вроде Fedora, утилита  lsof находится в  /usr/sbin. Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.

У этой команды есть множество ключей, рассмотрим самые важные.

  • p Позволяет указать  ID процесса.
  • d Позволяет указать номер дескриптора, о котором надо получить сведения.

Для того, чтобы узнать  PID текущего процесса, можно использовать специальную переменную окружения  $$, в которую оболочка записывает текущий  PID.

Ключ  a используется для выполнения операции логического  И над результатами, возвращёнными благодаря использованию двух других ключей:

Вывод сведений об открытых дескрипторах

Тип файлов, связанных с  STDINSTDOUT и  STDERR — CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.

Посмотрим на вызов команды  lsof из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:

#!/bin/bash

exec 3> myfile1

exec 6> myfile2

exec 7< myfile3

lsof a p $$ d 0,1,2,3,6,7

Вот что получится, если этот скрипт запустить.

Просмотр дескрипторов файлов, открытых скриптом

Скрипт открыл два дескриптора для вывода ( 3 и  6) и один — для ввода ( 7). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.

Подавление вывода

Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в  /dev/null. Это — что-то вроде «чёрной дыры».

Вот, например, как подавить вывод сообщений об ошибках:

ls al badfile anotherfile 2> /dev/null

Тот же подход используется, если, например, надо очистить файл, не удаляя его:

https://habr.com/ru/company/ruvds/blog/326594/

Понравилась статья? Поделить с друзьями:
  • B9b7 ошибка ситроен
  • B9a0 ошибка пежо 308
  • B998 ошибка пежо 308
  • B7f8c3 bmw ошибка
  • B7f8b8 ошибка bmw