Linux: bash спец. символы и переменные (> >> $ & # ~/$HOME $USER \ | /n \t ^M $? * ; ()), redirect stdout/stderr, ALIAS, bashrc, profile; программирование в bash (полезные скрипты, получение опций в скриптах, функции, условия, циклы, case, массивы)

  • man (смотрим по man man)
$ man 7 ping
No manual entry for ping in section 7
See 'man 7 undocumented' for help when manual pages are not available.
$ man 8 ping

$ man 1 top
    • section 1 – executable program / user commands
    • section 2 – system call
    • section 3 – library call
    • section 4 – special files
    • section 5 – configuration files
    • section 6 – games
    • section 7 – misc
    • section 8 – system commands (used by root)
    • section 9 – kernel routines
  • apropos – поиск строки в заголовках man для разных утилит/сервисов
% apropos apache
ab(1) - Apache HTTP server benchmarking tool
apachectl(8) - Apache HTTP Server Control Interface
httpd(8) - Apache Hypertext Transfer Protocol Server
logresolve(1) - Resolve IP-addresses to hostnames in Apache log files
rotatelogs(8) - Piped logging program to rotate Apache logs

% apropos apropos
man(1), apropos(1), whatis(1) - display online manual documentation pages
  • Узнать какой SHELL
~ echo $SHELL
/bin/bash

bash-3.2$ echo $SHELL # MACOS
/bin/zsh
  • https://www.gnu.org/software/bash/manual/ – manual по bash
  • wait <pid> – если процесс запущен в background, то wait позволяет подождать завершение execution процесса, пример использования
  • Universal CheatSheet – cheat.sh


bash-3.2$ curl cheat.sh/curl
cheat.sheets:curl
# curl
# Command-line tool for transferring data with URL syntax

# Process a single GET request, and show its output on stdout.
curl http://path.to.the/file

# Download a file and specify a new filename.
curl http://example.com/file.zip -o new_file.zip bash-3.2$ curl cheat.sh/insmod # insmod # Dynamically load modules into the Linux Kernel. # More information: <https://manned.org/insmod>. # Insert a kernel module into the Linux kernel: insmod path/to/module.ko
stdout/stderr

&> file – redirect all (stdout/stderr)

> file – redirect stdout

2> file – redirect stderr

ls > a.txt 2>b.txt  # в файле a.txt будет вывод ls, а в файл b.txt будем пустым т.к. нет ошибок
ls fdsfsdf > a.txt 2>b.txt # файл a.txt будет пустым, а в файле b.txt будет ошибка No such file or directory

 

profile/bashrc/export
  • Все описанное ниже может быть полезно, но в среднем сценарии дефолты не изменяются (чаще) или изменяются сразу везде (чтобы везде было одинаково).
  • В целом рекомендация изменять при необходимости bashrc, а не profile файл (основной) или даже файлы в profile.d директории т.к. несмотря на наличия profile он может по факту не загружаться при запуске каких то shell.
  • Так же еще есть файл bash_logout, который может запускать задачи при logout из системы – backup файлов, завершение процессов, приведение системы в дефолтное состояние для пользователя и проч.
  • Я практикую изменение формирования history файла – увеличение размера, добавление даты.

Profile считается универсальным для всех shell, а bash использует bashrc. Оба файла имеют глобальную версию (используется для всех пользователей) и пользовательскую (применяется для конкретного юзера, более приоритетный источник). 

global-system-wide: /etc/profile, /etc/bashrc, /etc/bash.bashrc, /etc/profile.d/*
per user: ~/.bash_profile, ~/.profile, ~/.bashrc

Per-user shell startup files override or modify system default definitions set by system-wide startup files. These files may be customized by individual users to suit their needs.

per-user startup files for bash shell users.
~/.bashrc - Defines functions and aliases. This file sources global definitions from the /etc/bashrc file.
~/.bash_profile - Sets environment variables. This file sources the ∼/.bashrc file to set functions and aliases.
~/.gnome2/ - Directory that holds environment settings when GNOME desktop is started. Only available if GNOME is installed.

Для прогрузки изменений без перезапуска сессии нужно использовать source команду на необходимый файл.

# MAIN
echo "HISTTIMEFORMAT='%d.%m.%Y %H:%M:%S: '" >> ~/.bashrc
source ~/.bashrc

# ALTERNATE
echo "HISTTIMEFORMAT='%d.%m.%Y %H:%M:%S: '" >> ~/.bash_profile
source ~/.bash_profile

Export позволяет посмотреть, что эскпортировано/объявлени в переменных, а при передаче export аргумента/переменной сделать ее доступной для всех дочерних shell процессов. Export команда может быть заменена декларацией set -o allexport, но в таком случае все переменные будут экспортироваться (используется редко).

# export
declare -x HISTTIMEFORMAT="%d/%m/%y %T "
declare -x HOME="/root"
declare -x LANG="en_US.UTF-8"
declare -x LC_CTYPE="UTF-8"
declare -x LOGNAME="root"
declare -x MAIL="/var/mail/root"
declare -x OLDPWD="/etc"
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/root"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_CLIENT="11.0.0.98 57196 22"
declare -x SSH_CONNECTION="11.0.0.98 57196 172.31.8.111 22"
declare -x SSH_TTY="/dev/pts/0"
declare -x TERM="xterm-256color"
declare -x USER="root"
declare -x XDG_RUNTIME_DIR="/run/user/0"
declare -x XDG_SESSION_CLASS="user"
declare -x XDG_SESSION_ID="1582"
declare -x XDG_SESSION_TYPE="tty"

 

Переменные
  • set – смотрим все переменные с их значениями (включая export)
  • export – смотрим только экспортированные переменные 
(ssh, bash) $SSH_CLIENT, $SSH_CONNECTION – переменные с выводом информации откуда/куда подключились по SSH
~ $ echo $SSH_CLIENT
89.179.128.38 59824 19922
~ $ echo $SSH_CONNECTION
89.179.128.38 59824 195.14.50.22 19922

$HOSTNAME – хранит имя хоста (сервера/ПК)

$HISTFILESIZE – подробно описано в logs

$HISTSIZE – подробно описано в logs

$HISTTIMEFORMAT – подробно описано в logs 

$STY – хранит имя сессии в screen

$PATH – важная переменная, указывающая директории, в которых оболочка bash будет искать исполняемые файлы, особенности с этой переменной возникают при запуске процесса из под другого пользователя – напр. автоматизация с использованием cron или логин из под другого пользователя (и даже с переходом в нужного из пользователя с другим PATH), возможность запуска скрипта из любой директории. Переменную можно изменять временно путем назначения нужного значения PATH переменной и на постоянной основе в .bashrc.
export PATH="$PATH:/root/"  # добавляем root директорию для поиска исполняемых файлов
export PATH="$PATH:." # добавляем текущую директорию для поиска исполняемых файлов

$PS1, $PS2 – отвечают за формирование строки пришествия в bash. PS string может быть в любом из этих мест, в зависимости от дистрибутива (Ubuntu, CentOS) – bashrc, profile. Статья по кастомизации приветствия, внизу так же описан пример как убрать hostname (\h) из приветствия модифицируя переменную PS, аналогичное справедливо и для username (\u), working directory (\w).

Bash configures its prompt by using the PS1 and the PS2 environmental variables.
PS1 defines the primary prompt that you will see. You see this every time you log in. By default, in Ubuntu systems, this should take the form of:
username@hostname: current_directory$

# echo $PS1
${debian_chroot:+($debian_chroot)}\u@\h:\w\$

How to hide machine name from displaying in terminal session screen - delete \h (which stands for hostname) from PS1 if you want to hide machine name from displaying in terminal.
спец символы

(Linux работа с текстом – tr, sort, cut, Linux спец. символы) в bash передача в консоль TAB делается через ctrl+v и после этого нажатия на TAB. С помощью tr можно подменить любой символ/последовательность на TAB, используя delimiter TAB можно отсортировать значения sort (-t), используя cut выделить столбцы по delimiter TAB (-d) (аналогично можно и AWK).

$ ls -ltr | tr -s ' ' ' ' | sort -t ' ' -k 5n | cut -d ' ' -f 5,9
15 dir_lst.txt
17 sw
32 ping_list.txt
32 ping_list2.txt
64 dir1
64 dir2
64 dir3
96 Music
128 Movies
128 Pictures
128 Public
192 Yandex.Disk.localized
224 Downloads
224 Desktop
256 Documents
2880 Library

\  – экранирование, например пробела в названии. Хотя лично я считаю лучше использовать скобки до и после строки с пробелом. Пример при работе с файлами/папками:

rm -r Miscellaneous\ Directory

& – перенос процесса в background как child процесса от текущего shell

rm nohup.out; nohup ./proc.py & tail -f nohup.out

; – замена newline – вместо Newline можно использовать ; тогда генерация однострочный скриптов становится еще более изощренной. С другой стороны – не надо делать файлы, менять их права, запускать. Вставил и получил результат.

read -p "Enter delay: "delay; echo "$delay"; sort -r -n -k 7 -k 4 /var/log/log.txt*


rm nohup.out; nohup ./proc.py & tail -f nohup.out

set -e – set exception, любой exception в любой строке приводит к полной остановке кода всего скрипта, по сути аналогия exception в коде python/ruby без try/except. По умолчанию без set -e execution переключается на строчку ниже. В качестве демонстрации достаточно задать set -e в самом интерпретаторе bash и выполнить ошибочную команду – интерпретатор прервет работу.

Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists of Commands), or a compound command (see Compound Commands) returns a non-zero status.

# example 1
% set -e
% ls d
ls: d: No such file or directory
[Процесс завершен]

# example 2
% cat test.sh
set -e
echo 123
echo 321
efdf
echo 333

% ./test.sh
123
321
./test.sh: line 4: efdf: command not found

#! – shebang символ, позволяет сделать ссылку на интерпретатор. В таком случае запуск скрипта возможен без указания интерпретатора – для запуска Ruby скрипта test.rb достаточно написать “test.rb” в командной строке вместо “ruby test.rb”.

#!/bin/bash – ссылка на интерпретатор sh
#!/usr/bin/ruby - на интерпретатор ruby
When running the script without a specified interpreter, the machine attempts to run the script as a shell script instead of a Ruby script. By putting Ruby in front of the script, we explicitly tell the machine to run the script through the Ruby interpreter, and the script runs as we would expect. But there's also a way to specify the interpreter inside the script, so you don't need to use the explicit call to Ruby every time you want to run the script. You can accomplish this by adding a shebang (#!) line at the beginning of the file!

Для лучшей переносимости кода между Unix-like системами рекомендуют использовать не прямой путь, а утилиту env, которая делает поиск в $PATH пути к интерпретатору самостоятельно.

#!/usr/bin/env bash
#!/usr/bin/env ruby

Лучшей практикой, несмотря на то, что по умолчанию исполняемые файлы обрабатываются посредством SH, по аналогии с expect, perl, ruby и  прочими, добавлять ссылку на интерпретатор (прямую или лучше через env) в начале кода во всех BASH скриптам.

В случае жесткого задания пути, для поиска папки, в которой находится интерпретатор, можно использовать whereis.

$ whereis bash
bash: /usr/local/bin/bash /usr/local/man/man1/bash.1.gz /usr/ports/shells/bash

$ whereis expect
expect: /usr/local/bin/expect /usr/local/man/man1/expect.1.gz /usr/ports/lang/expect

Так же кто-то заморачивается и не использует env – вместо него вызывает скрипт как bash, обнаруживает интерпретатор python и передает ему все аргументы. Не знаю насколько такой подход оправдан, на первый взгляд выглядит излишеством.

"source" "find_python.sh" "--local"
"exec" "$PYTHON" "$0" "$@"

Слишком длинная строка

Возможна трабла с сохранением в файл строки из-за ограничения длины строки в Linux.

Решается echo:

echo "USER-2019-0915 … many words … USER-2019-0609" | tr ' ' '\n' | wc

 

Примеры ALIAS

Пример – по команде ll выводить список (-l) и подсвечивать директории через color=auto (в MAC работает через -G).

# alias
alias ll='ls $LS_OPTIONS -l'

# echo $LS_OPTIONS
--color=auto

$ ll
total 0a
drwx------+ 5 petrredkin staff 160 Mar 24 15:24 Desktop
drwx------+ 8 petrredkin staff 256 Mar 21 22:24 Documents
drwx------+ 5 petrredkin staff 160 Mar 23 23:08 Downloads
drwx------@ 87 petrredkin staff 2784 Mar 21 23:20 Library
drwx------ 3 petrredkin staff 96 Mar 21 20:08 Movies
drwx------+ 3 petrredkin staff 96 Mar 21 20:08 Music
drwx------+ 4 petrredkin staff 128 Mar 21 20:10 Pictures
drwxr-xr-x+ 4 petrredkin staff 128 Mar 21 20:08 Public

 

программирование в bash

exit code
При написании скриптов строго говоря нужно знать один exit code: 0 (success).
 
Остальные это не успех по разным причинам. При скриптинге я обычно использовал exit 1 для обозначения любой ошибки, не ориентируясь на таблицу по ссылке выше или другую (противоречивую) информацию по каким-то якобы нормам.
 
Получение exit code status:
# echo $?
1
Пользовательский ввод

Bash read user input

read -p "Enter var: " var
echo "$varv"
Условия

Сравнение строк.

Нулевая строка.

if [[ $var == "" ]]; then
echo "choto"
fi

Сравнение численных в bash:

https://stackoverflow.com/questions/18668556/comparing-numbers-in-bash
if (( $delay > 900 )); then
echo "lol"
fi

if [[ "$delay" -gt "900" ]]; then
echo "lol"
fi
CASE

Пример из configure netmap (автоселект ОС):

#!/bin/sh

os=$(uname -s)
topdir=$(cd $(dirname $0); pwd)

case $os in
Linux)
$topdir/LINUX/configure "$@";;
FreeBSD)
$topdir/FreeBSD/configure "$@";;
*)
echo "Sorry, $os is not supported"
exit 1;;
esac
Функции

Можно вначале функции добавить keyword function, но работает и без этого

select_res() {
grep $1 $2
}

select_res  $1 $2

Пример в виде создания своей “команды/утилиты” (по сути built in bash) через функцию в bashrc.

vi .bashrc 
hello_world() {
   echo "Hello_World"
}

# source .bashrc
# hello_world
Hello_World

Пример создания функции-команды по поиску на сайте cheat.sh инфы:

vi .bashrc 
cheat() {
  curl "https://cheat.sh/$1"
}

# source .bashrc
# cheat ps
Hello_World
МАССИВЫ (DICTIONARY, HASH)
declare -A animals=( ["moo"]="cow" ["woof"]="dog")
echo "${animals[moo]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals[$sound]}"; done
опции в скриптах (GETOPS)
  • Множество примеров тут.

Простой пример с четырьмя опциями – a, b, c, f. Три имеют двоеточие в getops и поэтому должны передаваться с аргументами опции, опция f не имеет аргументов и должна находится последней при запуске утилиты (иначе последующие после f опции игнорируются).

while getopts "fa:b:c:" OPT
do
case $OPT in
a) echo "Found option $OPT with arg $OPTARG";;
b) echo "Found option $OPT with arg $OPTARG";;
c) echo "Found option $OPT with arg $OPTARG";;
f) echo "Found option $OPT without arg";;
esac
done

Usage

# ./sw.sh -a test1 -b test2 -c test3 -f test4  # последний аргумент - f передали с опцией, но только от этого нет толку т.к. это не соответствует настройкам
Found option a with arg test1
Found option b with arg test2
Found option c with arg test3
Found option f without arg

# ./sw.sh -a test1 -b test2 -f test4 -c test3 # последний аргумент -c не передался т.к. перед ним аргумент -f без опций
Found option a with arg test1
Found option b with arg test2
Found option f without arg

 

 

 

СКрипты
скрипт по мониторингу (процесса/изменения файла)

Простейший однострочный скрипт, который позволяет онлайн (апдейт каждую секунду) следить за изменением процесса/файла и проч. По сути аналог утилиты watch.

while true; do clear; ps -x; echo; sleep 1; done
скрипт по поиску строк одного файла в другом файле
  • Файл из которого берем строки для поиска указываем в первой переменной.
  • Файл в котором делаем поиск указываем во второй переменной.

Можно убрать якоря, чтобы успешный результат считался не только по полному match строки.

usage:
./str_existance.sh to_find.txt where_find.txt

code:
#!/bin/bash
cat $1 | while read sw

do

 RESULT=$(grep ^"$sw"$ $2)
 if [[ "$RESULT" == "" ]]; then
   echo $sw";"not_exist
 else
   echo $sw";"exist
 fi

done
скрипт по генерации списка IP

Простой скрипт по генерации большого количества IP адресов на базе стартового адреса и необходимого количества последовательных адресов (в примере 100к):

usage:
generate_range.sh 7.7.7.1 100000

code:
#!/bin/bash ip1=$(echo "$1" | awk -F'.' '{print $1}') ip2=$(echo "$1" | awk -F'.' '{print $2}') ip3=$(echo "$1" | awk -F'.' '{print $3}') ip4=$(echo "$1" | awk -F'.' '{print $4}') limit=$(echo "$2") count=0 for a in $(seq $ip1 255); do for b in $(seq $ip2 255); do for c in $(seq $ip3 255); do for d in $(seq $ip4 255); do if [[ $count == $limit ]]; then exit fi echo "$a.$b.$c.$d" let count++ done done done done
скрипт по генерации списка портов на основе диапазона или последовательности

Набросал скрипт по генерации списка портов на основе диапазона или последовательности. Ест любые известные мне комбинации, использовал для многих кейсов после получения списка из конфига/консоли. Для генерации из диапазона используется подвызов eval.

#!/bin/bash
echo "$@" | sed 's/,/ /g' | tr " " "\n" | sed 's/[[:space:]]//g' | grep '[0-9]' | while read port
do
RANGE_DETECTION=$(echo $port | grep "-")
if [[ "$RANGE_DETECTION" == "" ]]; then
 echo $port
else
 port=$(echo $port | sed 's/-/../')
 echo `eval echo {$port}` | tr " " "\n"
fi
done

Usage:

$ port_list_from_range 1 
 1

$ port_list_from_range 10-11,13-14
 10
 11
 13
 14

$ port_list_from_range 10-11,13-14 23,24-28
 10
 11
 13
 14
 23
 24
 25
 26
 27
 28

 

Socket

Так же как и ниже с JSON, безусловно лучше использовать python для работы с сокетами. Но если выхода нет – то bash так же возможно использовать socket для приема и передачи файлов.

Чтобы понять, насколько это костыли, достаточно посмотреть, как закрываются соединения 🙂

Первая команда закрывает входное соединение, а вторая закрывает выходное соединение.
$ exec {file-descriptor}<&-
$ exec {file-descriptor}>&-

Пример скрипта, который отправляет файл на указанный IP PORT с использованием TCP сокета вместе с checksum MD5 этого файла (если точнее – сначала передается MD5, затем сам файл). Другие примеры (HTTP GET, SSH CONN) с использованием файлов устройства /dev/tcp и /dev/udp для передачи и приема файлов по ссылке выше.

- Файловые дескрипторы 0, 1 и 2 зарезервированы для stdin, stdout и stderr соответственно. Таким образом, вы должны указать 3 или выше (в зависимости от того, что не используется) в качестве дескриптора файла.
- «<>» означает, что сокет открыт как для чтения, так и для записи. В зависимости от ваших потребностей, вы можете открыть сокет только для чтения (<) или только для записи (>).

#!/bin/bash
IP=$1
PORT=$2
FILE=$3

md5=`md5sum -b $FILE`
exec 3<>/dev/tcp/$IP/$PORT
echo $md5 >&3
sleep 1
cat $FILE >&3

 

JSON

Парсить json через bash можно с использованием jq, но он не включен в стандартные утилиты, поэтому лучше (я так делаю) использовать python и забыть в данном случае про bash. Есть так же промежуточный вариант (костыль) подключения в pipeline python или ruby.

Linux утилиты для работы с Excel в консоли

Найти нормальные не удалось, использовал Ruby gem Spreadsheet и PHP библиотеку PHPExcel. Те, что находил, весили ~300мб (SSConvert, Unoconv, csv2odf, xls2csv).

 

 

 

questions

In Bash, inserting 2>&1 after a command redirects:

A. standard error to standard input.

B. standard input to standard error.

C. standard output to standard error.

D. standard error to standard output.

E. standard output to standard input.

D
https://tecadmin.net/io-redirection-operator-in-bash/
2>&1 is an I/O redirection operator used in Bash that redirects the stderr stream to the same destination as the stdout stream. In other words, it merges the error output with the regular output
https://stackoverflow.com/questions/818255/what-does-21-mean
File descriptor 1 is the standard output (stdout).
File descriptor 2 is the standard error (stderr).
At first, 2>1 may look like a good way to redirect stderr to stdout. However, it will actually be interpreted as "redirect stderr to a file named 1". & indicates that what follows and precedes is a file descriptor, and not a filename. Thus, we use 2>&1. Consider >& to be a redirect merger operator.

What output will be displayed when the user fred executes the following command? echo ‘fred $USER’

A. fred fred

B. fred /home/fred/

C. ‘fred $USER’

D. fred $USER

E. ‘fred fred’

Answer: A
root@serv:~# echo "fred $USER"
fred root

Which of the following commands redirects the output of ls to standard error?

A. ls >-1

B. ls <<ERR

C. ls >&2

D. ls >>2

E. ls |error

Answer: C

Explanation
This command redirects the output of ls to standard error, which is file descriptor 2 by default. The syntax of the command is:
ls >& file_descriptor
The ls command is a utility that lists the files and directories in the current working directory or a specified directory. The >& symbol is a redirection operator that redirects the standard output of a command to another file descriptor, which can be a file, a device, or another stream. The file_descriptor is the number of the file descriptor to which the output is redirected.
Therefore, the command ls >&2 will run the ls command and redirect its output to file descriptor 2, which is standard error. This means that the output of ls will not be displayed on the screen, but sent to the standard error stream, which can be used for error handling or logging purposes.

The other commands are incorrect for the following reasons:
* A, ls >-1: This command will not redirect the output of ls to standard error, but it will cause an error.
The > symbol is a redirection operator that redirects the standard output of a command to a file or device, overwriting any existing content. The -1 argument is not a valid file name or device name, and it will cause the shell to report an error and exit.
* B, ls <<ERR: This command will not redirect the output of ls to standard error, but it will use a here document as the standard input of ls. The << symbol is a redirection operator that redirects the standard input of a command from a here document, which is a block of text that follows the command. The ERR argument is the delimiter that marks the end of the here document. However, the ls command does not read from the standard input, and it will ignore the here document. The command will display the files and directories in the current working directory on the screen, as usual.
* D, ls >>2: This command will not redirect the output of ls to standard error, but it will append the output of ls to a file named 2. The >> symbol is a redirection operator that redirects the standard output of a command to a file or device, appending to any existing content. The 2 argument is the name of the file to which the output is appended. If the file does not exist, it will be created. The command will not display anything on the screen, but write the output of ls to the file 2.
* E, ls |error: This command will not redirect the output of ls to standard error, but it will pipe the output of ls to another command named error. The | symbol is a pipe operator that redirects the standard output of one command to the standard input of another command. The error argument is the name of the command that receives the output of ls as its input. However, there is no such command named error in the Linux system, and the shell will report an error and exit.

Which of the following characters can be combined with a separator string in order to read from the current input source until the separator string, which is on a separate line and without any trailing spaces, is reached?

A. <<

B. <|

C. !<

D. &<

Answer: A

The character that can be combined with a separator string in order to read from the current input source until the separator string, which is on a separate line and without any trailing spaces, is reached is the "<<" character.

Therefore, the correct answer is (A) "<<"

This is known as the "here-document" or "here-doc" syntax in shell scripting. It is used to specify a block of input text within a script. The syntax allows you to input multiple lines of text until a specified delimiter is reached.

For example, suppose you want to create a file with some text in it using a script. Instead of manually typing in the text, you can use the here-doc syntax as follows:

$ cat > myfile.txt << END > This is the first line of my file. > This is the second line. > And this is the third. > END

In the above example, "<< END" tells the shell to start reading input from the following lines until it sees the word "END" on a line by itself. The text between "<< END" and "END" is then written to the file "myfile.txt".

The separator string ("END" in the above example) can be any string you choose, as long as it does not contain any leading or trailing spaces.

So, option (A) "<<", is the correct answer to the question.

Which of the following shell redirections will write standard output and standard error output to a file named filename?

A. 2>&1 >filename

B. >filename 2>&1

C. 1>&2>filename

D. >>filename

E. 1&2>filename

Answer: B
https://stackoverflow.com/questions/876239/how-to-redirect-and-append-both-standard-output-and-standard-error-to-a-file-wit

cmd >>file.txt 2>&1
Bash executes the redirects from left to right as follows:
1) >>file.txt: Open file.txt in append mode and redirect stdout there.
2) 2>&1: Redirect stderr to "where stdout is currently going". In this case, that is a file opened in append mode. In other words, the &1 reuses the file descriptor which stdout currently uses.

Leave a Reply