1

Автор: Кузнецов Константин

[size=7]Пишем скрипты в Linux (обучение на примерах)[/size]

Содержание:
1. Введение
2. Обучение написанию сценариев на внутреннем языке BASH (Перевод с англ.)
3. Используемая и рекомендуемая литература

----------------------------------------------------------------------------------

[size=6]1. Введение[/size]

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

Материал из Википедии — свободной энциклопедии
Скриптовый язык (англ. scripting language, в русскоязычной литературе принято название язык сценариев) — язык программирования, разработанный для записи «сценариев», последовательностей операций, которые пользователь может выполнять на компьютере. Простые скриптовые языки раньше часто называли языками пакетной обработки (batch languages или job control languages). Сценарии обычно интерпретируются, а не компилируются (хотя часто сценарии компилируются каждый раз перед запуском).
В прикладной программе, сценарий (скрипт) — это программа, которая автоматизирует некоторую задачу, которую без сценария пользователь делал бы вручную, используя интерфейс программы.

----------------------------------------------------------------------------------

[size=6]2. Обучение написанию сценариев на внутреннем языке BASH[/size]
оригинал: http://www.linuxconfig.org/Bash_scripting_Tutorial

Это руководство предполагает отсутствие предварительных знаний о методике написания сценариев (далее скриптов) с помощью внутреннего языка Bash. С помощью данного руководства вы обнаружите в скором времени, что написание скриптов очень простая задача. Давайте начнем наше обучение с простого сценария, выполняющего вывод строки "Hello World!" (в перев. с англ. - Всем привет!)

1) Сценарий "Всем привет"
Вот ваш первый пример bash-скрипта:

#!/bin/bash
echo "Hello World"

Переходим в директорию, содержащую наш файл hello_world.sh и делаем его исполняемым:

$ chmod +x hello_world.sh

Запускаем скрипт на выполнение

$ ./hello_world.sh

2) Простой архивирующий bash-скрипт

#!/bin/bash
tar -czf myhome_directory.tar.gz /home/user

$ ./backup.sh
tar: Removing leading '\' from member names
$ du -sh myhome_directory.tar.gz
41M myhome_directory.tar.gz

3) Работа с переменными
В данном примере мы объявляем простую переменную и выводим её на экран с помощью команды echo

#!/bin/bash
STRING="HELLO WORLD!!!"
echo $STRING

$ ./hello_world.sh
HELLO WORLD!!!

Наш архивирующий скрипт с переменными:

#!/bin/bash
OF=myhome_directory_$(date +%Y%m%d).tar.gz
IF=/home/user
tar -czf $OF $IF

$ ./backup.sh
tar: Removing leading '\' from member names
$ du -sh *tar.gz
41M myhome_directory_20100123.tar.gz

3.1) Глобальные и локальные переменные

#!/bin/bash
# Объявляем глобальную переменную
# Такая переменная может использоваться в любом месте этого скрипта
VAR="global variable"
function bash {
# Объявляем локальную переменную
# Такая переменная действительна только для функции, в которой её объявили
local VAR="local variable"
echo $VAR
}
echo $VAR
bash
# Обратите внимание, что глобальная переменная не изменилась
echo $VAR

$ ./variables.sh
global variable
local variable
global variable

4) Передаем аргументы в скрипт

#!/bin/bash
# Используйте предопределенные переменные для доступа к аргументам
# Выводим аргументы на экран
echo $1 $2 $3 ' -> echo $1 $2 $3'

#Мы так же можем получить доступ к аргументам через специальный массив args=("$@")
# Выводим аргументы на экран
echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}'

# Используйте переменную $@ для вывода всех аргументов сразу
echo $@ ' -> echo $@'

Используйте переменную $# для вывода количества переданный в скрипт аргументов
echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#'

$ ./arguments.sh Bash Scripting Tutorial
Bash Scripting Tutorial -> echo $1 $2 $3
Bash Scripting Tutorial -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}
Bash Scripting Tutorial -> echo $@
Number of arguments passed: 3  -> echo Number of arguments passed: $#

5) Выполнение в скрипте команд оболочки

#!/bin/bash
# используйте обратные кавычки " ` ` " для выполнения команды оболочки
echo `uname -o`
# теперь попробуем без кавычек
echo uname -o

$ uname -o
GNU/Linux
$ ./bash_backtricks.sh
GNU/Linux
uname -o

Как видим, во втором случае вывелась сама команда, а не результат её выполнения

6) Читаем пользовательский ввод (интерактивность)

#!/bin/bash
echo -e "Hi, please type the word: \c "
read  word
echo "The word you entered is: $word"
echo -e "Can you please enter two words? "
read word1 word2
echo "Here is your input: \"$word1\" \"$word2\""
echo -e "How do you feel about bash scripting? "
# read command now stores a reply into the default build-in variable $REPLY
read
echo "You said $REPLY, I'm glad to hear that! "
echo -e "What are your favorite colours ? "
# -a makes read command to read into an array
read -a colours
echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)"

$ ./read.sh
Hi, please type the word: something
The word you entered is: something
Can you please enter two words?
Debian Linux
Here is your input: "Debian" "Linux"
How do you feel about bash scripting?
good
You said good, I'm glad to hear that!
What are your favorite colours ? 
blue green black
My favorite colours are also blue, green and black  :-)

7) Использование ловушки

#!/bin/bash
# объявляем ловушку
trap bashtrap INT
# очищаем экран
clear;
# функция ловушки выполняется, когда пользователь нажимает CTRL-C:
# На экран будет выводиться => Executing bash trap subrutine !
# но скрипт будет продолжать выполняться
bashtrap()
{
    echo "CTRL+C Detected !...executing bash trap !"
}
# скрипт будет считать до 10
for a in `seq 1 10`; do
    echo "$a/10 to Exit."
    sleep 1;
done
echo "Exit Bash Trap Example!!!"

$ ./trap.sh
1/10
2/10
3/10
4/10
5/10
6/10
CTRL+C Detected !...executing bash trap !
7/10
8/10
9/10
CTRL+C Detected !...executing bash trap !
10/10
Exit Bash Trap Example!!!

Как видим, сочетание клавишь Ctrl-C не остановило выполнение скрипта.

af Массивы
8.1) Объявляем простой массив

#!/bin/bash
# Объявляем простой массив с 4 элементами
ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux )
# Получаем количество элементов в массиве
ELEMENTS=${#ARRAY[@]}

# выводим в цикле каждый элемент массива
for (( i=0;i<$ELEMENTS;i++)); do
    echo ${ARRAY[${i}]}
done

$./arrays.sh
Debian Linux
Redhat Linux
Ubuntu
Linux

8.2) Заполняем массив значениями из файла

#!/bin/bash
# Объявляем массив
declare -a ARRAY
# Команда exec <filename перенаправляет ввод со stdin на файл. С этого момента весь ввод, вместо
# stdin (обычно это клавиатура), будет производиться из этого файла. Это дает возможность читать
# содержимое файла, строку за строкой, и анализировать каждую введенную строку с помощью sed и/или awk.
exec 10<bash.txt
let count=0

while read LINE <&10; do

    ARRAY[$count]=$LINE
    ((count++))
done

echo Number of elements: ${#ARRAY[@]}
# Вывод значений массива
echo ${ARRAY[@]}
# закрываем файл
exec 10>&-

$ cat bash.txt
Debian Linux
Redhat Linux
Ubuntu
Linux
$ ./arrays.sh
Number of elements: 4
Debian Linux Redhat Linux Ubuntu Linux

9) Условия "если-то-иначе"
9.1) Простое использование "если-иначе" условий
Обратите внимание на пробелы в квадратных скобках, без которых условие работать не будет.

#!/bin/bash
directory="./BashScripting"

# проверяем наличие директории
if [ -d $directory ]; then
    echo "Directory exists"
else
    echo "Directory does not exists"
fi

$ ./if_else.sh
Directory does not exists
$ mkdir BashScripting
$ ./if_else.sh
Directory exists

9.2) Вложенные "если-иначе" условия

#!/bin/bash
# Объявляем переменную со значением 4
choice=4
# Выводим на экран
echo "1. Bash"
echo "2. Scripting"
echo "3. Tutorial"
echo -n "Please choose a word [1,2 or 3]? "
# Выполняем, пока переменная равна четырем
# Зацикливание
while [ $choice -eq 4 ]; do

# читаем пользовательский ввод
read choice
# вложенное "если-иначе" условие
if [ $choice -eq 1 ] ; then

        echo "You have chosen word: Bash"

else                   

        if [ $choice -eq 2 ] ; then
                 echo "You have chosen word: Scripting"
        else
         
                if [ $choice -eq 3 ] ; then
                        echo "You have chosen word: Tutorial"
                else
                        echo "Please make a choice between 1-3 !"
                        echo "1. Bash"
                        echo "2. Scripting"
                        echo "3. Tutorial"
                        echo -n "Please choose a word [1,2 or 3]? "
                        choice=4
                fi   
        fi
fi
done

$ ./nested.sh
1. Bash
2. Scripting
3. Tutorial
Please choose a word [1,2 or 3]? 
5
Please make a choice between 1-3 !
1. Bash
2. Scripting
3. Tutorial
Please choose a word [1,2 or 3]? 
4
Please make a choice between 1-3 !
1. Bash
2. Scripting
3. Tutorial
Please choose a word [1,2 or 3]? 
3
You have chosen word: Tutorial

Таким образом сначала тело цикла "while" выполняется, т.к. переменная choice изначально равна четырем. Потом читаем в неё пользовательский ввод, и если ввод не равен 1,2 или 3 то делаем нашу переменную снова равную 4, в связи с чем тело цикла повторяется (снова необходимо вводить 1,2 или 3).

10) Сравнения
10.1) Арифметические сравнения

-lt     <
-gt     >
-le     <=
-ge     >=
-eq     ==
-ne     !=

#!/bin/bash
# Объявляем переменные с целочисленными значениями
NUM1=2
NUM2=2
if [ $NUM1 -eq $NUM2 ]; then
    echo "Both Values are equal"
else
    echo "Values are NOT equal"
fi

$ ./equals.sh
Both Values are equal

#!/bin/bash
# Объявляем переменные с целочисленными значениями
NUM1=2
NUM2=3
if [ $NUM1 -eq $NUM2 ]; then
    echo "Both Values are equal"
else
    echo "Values are NOT equal"
fi

$ ./equals.sh
Values are NOT equal

#!/bin/bash
# Объявляем переменные с целочисленными значениями
NUM1=2
NUM2=1
if   [ $NUM1 -eq $NUM2 ]; then
    echo "Both Values are equal"
elif [ $NUM1 -gt $NUM2 ]; then
    echo "$NUM1 is greater then $NUM2"
else
    echo "$NUM2 is greater then $NUM1"
fi

$ ./equals.sh
2 is greater then 1

10.2) Символьно-текстовые сравнения

=     одинаковые
!=     не одинаковые
<     меньще чем
>     больше чем
-n s1    переменная s1 не пустая
-z s1    переменная s1 пустая

#!/bin/bash
# Объявляем символьную переменную S1
S1="Bash"
# Объявляем символьную переменную S2
S2="Scripting"
if [ $S1 = $S2 ]; then
    echo "Both Strings are equal"
else
    echo "Strings are NOT equal"
fi

$ ./statement.sh
Strings are NOT equal

#!/bin/bash
# Объявляем символьную переменную S1
S1="Bash"
# Объявляем символьную переменную S2
S2="Bash"
if [ $S1 = $S2 ]; then
    echo "Both Strings are equal"
else
    echo "Strings are NOT equal"
fi

$ ./statement.sh
Both Strings are equal

11) Проверка файлов

-b filename    Block special file
-c filename    Special character file
-d directoryname    Check for directory existence
-e filename    Check for file existence
-f filename    Check for regular file existence not a directory
-G filename    Check if file exists and is owned by effective group ID.
-g filename    true if file exists and is set-group-id.
-k filename    Sticky bit
-L filename    Symbolic link
-O filename    True if file exists and is owned by the effective user id.
-r filename    Check if file is a readable
-S filename    Check if file is socket
-s filename    Check if file is nonzero size
-u filename    Check if file set-ser-id bit is set
-w filename    Check if file is writable
-x filename    Check if file is executable

#!/bin/bash
file="./file"
if [ -e $file ]; then
    echo "File exists"
else
    echo "File does not exists"
fi

$ ls
file.sh
$ ./file.sh
File does not exists
$ touch file
$ ls
file  file.sh
$ ./file.sh
File exists

Аналогично для примера мы можем использовать "в то время как" петли, чтобы проверить, если файл не существует. Этот сценарий будет спать, пока файл не существует. Обратите внимание на Bash отрицатель "!" что сводит на нет (инвертирует) -e опцию.

12) Циклы
12.1) Цикл For

#!/bin/bash
# for цикл
for f in $( ls /var/ ); do
    echo $f
done

Запуск for-цикла из командной строки bash:

$ for f in $( ls /var/ ); do echo $f; done 
$ for f in $( ls /var/ ); do echo $f; done
backups
cache
crash
games
lib
local
lock
log
mail
opt
run
spool
tmp
www

12.2) While цикл

#!/bin/bash
COUNT=6
# while цикл
while [ $COUNT -gt 0 ]; do
    echo Value of count is: $COUNT
    let COUNT=COUNT-1
done

$ ./while_loop.sh
Value of count is: 6
Value of count is: 5
Value of count is: 4
Value of count is: 3
Value of count is: 2
Value of count is: 1

12.3) Until цикл

#!/bin/bash
COUNT=0
# until цикл
until [ $COUNT -gt 5 ]; do
        echo Value of count is: $COUNT
        let COUNT=COUNT+1
done

$ ./until_loop.sh
Value of count is: 0
Value of count is: 1
Value of count is: 2
Value of count is: 3
Value of count is: 4
Value of count is: 5

12.4) Циклы с неявными условиями
В следующем примере условием while-цикла является наличие стандартного ввода.
Тело цикла будет выполняться пока есть чему перенаправляться из стандартного вывода в команду read.

#!/bin/bash
# Данный скрипт будет искать и удалять пробелы
# в файлах, заменяя их на подчеркивания
DIR="."
Управление циклом с командой read путем перенаправления вывода в цикле.
find $DIR -type f | while read file; do
# используем POSIX-класс [:space:] чтобы найти пробелы в именах файлов
if [[ "$file" = *[[:space:]]* ]]; then
# замена пробелов подчеркиваниями
mv "$file" `echo $file | tr ' ' '_'`
fi;
done

$ ls -1
script.sh
$ touch "file with spaces"
$ ls -1
file with spaces
script.sh
$ ./script.sh
$ ls -1
file_with_spaces
script.sh

13) Функции

#!/bin/bash
# Функции могут быть объявлены в любом порядке
function function_B {
        echo Function B.
}
function function_A {
        echo $1
}
function function_D {
        echo Function D.
}
function function_C {
        echo $1
}
# Вызываем функции
# передаем параметр в функцию function A
function_A "Function A."
function_B
# передаем параметр в функцию function C
function_C "Function C."
function_D

$ ./functions.sh
Function A.
Function B.
Function C.
Function D.

14) Оператор выбора - Select

#!/bin/bash
PS3='Choose one word: '
# select
select word in "linux" "bash" "scripting" "tutorial"
do
  echo "The word you have selected is: $word"
# Прерываем, в противном случае цикл будет бесконечный.
  break 
done
exit 0

$ ./select.sh
1) linux
2) bash
3) scripting
4) tutorial
Choose one word: 4
The word you have selected is: tutorial

15) Оператор выбора - Case

#!/bin/bash
echo "What is your preferred programming / scripting language"
echo "1) bash"
echo "2) perl"
echo "3) phyton"
echo "4) c++"
echo "5) I do not know !"
read case;
# простая структура case-выбора
# обратите внимание, что в данном примере $case - всего лишь переменная
# и не обязана так называться. Это лишь пример
case $case in
    1) echo "You selected bash";;
    2) echo "You selected perl";;
    3) echo "You selected phyton";;
    4) echo "You selected c++";;
    5) exit
esac

$ ./case.sh
What is your preferred programming / scripting language
1) bash
2) perl
3) phyton
4) c++
5) I do not know !
4
You selected c++

----------------------------------------------------------------------------------

[size=6]3. Используемая и рекомендуемая литература[/size]

Более подробную информацию можно получить из различных источников, например отсюда
оригинал: http://www.linuxconfig.org/Bash_scripting_Tutorial
http://ruslandh.narod.ru/howto_ru/Bash-Prog-Intro/
http://bug.cf1.ru/2005-03-17/programmin … -book.html

2

а  как вписать в  автозагрузку скрипт  который  лежит /home/oleg/scripts  имя скрипта conky.sh  ?

Грамматические ошибки прошу не считать, Ubuntu 10.10

3

Vartonst, вариантов масса, способ зависит от используемого ПО.
Один из них: добавить в ~/.xsession (или .xinitrc)

/home/oleg/scripts/conky.sh &

только не в конец, а перед запуском оконного менеджера.
К несчастью, я не уверен, что всё пойдёт гладко, ибо наверняка вы используете gdm ): (или kdm)
Anyway, http://en.gentoo-wiki.com/wiki/HOWTO_Autostart_Programs здесь Вы наверняка найдёте решение

Труслив. Тороплив. Бестолков. Продажен. В сложной ситуации теряется до бесчувствия. Подвержен панике. Легко теряется от всего. Содеянного не помнит. В мыслях путается, в письменной речи ошибается. От своих слов легко отказывается.

4 (20.04.2010 13:31:37 отредактировано ДимOn)

ДимOn пишет:

А покажите пример скрипта, как с клиента подключиться к ssh-серверу, перенести на машину клиента определенные файлы и отключиться.

Нашел способ, так как авторизация по ключу не очень подходит, то делаем так:
Сначала ставим  sshpass

aptitude install sshpass

А теперь скрипт, для синхронизации

#!/bin/sh
sshpass -p пароль_к_ssh rsync -e ssh --progress -thvr имя_пользователя@IP:/Указываем_путь_откуда/ /Указываем_путь_куда/

5 (21.04.2010 15:45:29 отредактировано 6OTuHO4Er)

в crontab стоит бэкап баз демоном rsync.
как запихнуть, что он делает, все в $(date +...).log? кроме --log-file='/...'

6

а чем --log-file не устраивает?

7

6OTuHO4Er пишет:

в crontab стоит бэкап баз демоном rsync.
как запихнуть, что он делает, все в $(date +...).log? кроме --log-file='/...'

..... 1>/var/log/aaa.log 2>/var/log/aaa.errors.log

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

8 (27.02.2011 08:18:45 отредактировано Nigelist)

Добрый день! Пока не умею писать скрипты. В общем передо мной стоит задача - настроить бэкап БД постгреса со следующими параметрами:

  • чтобы бэкап имел максимально сжатие

  • Кол-во хранимых бэкапов в определенном каталоге не превышал определенного кол-ва

  • Имя бэкапа задавалось исходя из текущей даты, например: - postgres_YYYY-MM-DD

Может кто поможет с этим делом?

9

Или может кто нибудь переделает этот скрипт?

#!/bin/bash
date=`date "+%Y_%m_%d"`;                                                 # Получим текущую дату в устраивающем нас формате и запишем ее в переменную $date
days_open_store='14';                                                   # Сколько дней хранить незашифрованные бэкапы
days_crypt_store='60';                                             # Сколько дней хранить зашифрованные бэкапы
dir_crypt=/media/remote_share                                   # Каталог для зашифрованных бэкапов, надо чтобы был смонтирован.
dir_open=/local_backup                                                   # Каталог для незашифрованных бэкапов (нужны, чтобы можно было быстро восстановить упавшую дазу одынце)
gpgdir=/backup/gpg_dir                                                             # Каталог, где лежит .gpg-файл с открытым ключом, которым будут шифроваться бэкапы
gpgkey='0xABCDEFGH';                                                     # PGP_ID ключа для зашифровки бэкапов
# GnuPG compessing & trust options
gpgzip='--compress-algo zip --compress-level 9 --trust-model always --batch'; # Параметры шифрования
rar_bin=/bin/rar                                                                 # Путь к бинарю к консольным никсовым RAR-ом
# Command and options for PostgreSQL Dump
pgdump_binc='/usr/bin/pg_dump -i -h localhost -p 5432 -U postgres -F c -b -o -v -f'; # Часть команды для генерации сжатых дампов
pgdump_bin='/usr/bin/pg_dump -h localhost -U postgres '; # Часть команды для генерации обычных SQL-дампов
mysqldump_bin='mysqldump -u_backuper -hlocalhost -pPASSWD'; # Часть команды для дампинга MySQL


echo "=== BackUp script for Server === [$date]";
mkdir $dir_open/$date
mkdir $dir_crypt/$date
sync


echo 'Make open archives ...';
cd $dir_open/$date
$pgdump_binc 1c_postgre_compressed_dump.bak 1c_database
$pgdump_binc postgre_sysdb_compressed.bak postgres
$pgdump_bin 1c_database | gzip > 1c_postgre_sql_dump.gz
$pgdump_bin postgres | gzip > postgre_sysdb_sql_dump.gz

/* Тут раскурено не до конца. 1C:Конфигуратор 8.1 работает в WINE, и нормально выгружает / загружает базы через dt-файлы. Но из консоли не работает, пишет, что не может соединиться с X-сервером. Похоже, что даже в режиме /DumpIB конфигуратор стартует как графическое приложение, так что как это решить в консоли, пока не понятно. Буду рад совету !!! */
#sudo -ucyka -H='/home/cyka' wineconsole /home/cyka/wine_c/windows/system32/cmd.exe /c 'C:/1cv81/bin/1cv8.exe config /s Server\1c_database /DisableStartupMessages /n backuper /p PASSWD /DumpIB D:/1C.dt'
#   mv /.../.../1C.dt $dir_open/$date # Надо бы переменную с датой вставить в предыдущую строку, но все равно эта часть пока не работает.

$rar_bin a -r -rr5 -dh -mdG -ep1 -ol -ow manager_files.rar /mnt/sda1/smb/managers
$rar_bin a -r -rr5 -dh -mdG -ep1 -ol -ow buh_files.rar /mnt/sda1/smb/buh

$mysqldump_bin --databases --all-databases | gzip -c > _mysql_sql_dump.gz # Это правильный дамп.
#$rar_bin a -r -rr5 -dh -mdG -ep1 -ol -ow _mysql_db.rar /var/mysql/data # А вот так делать не стоит.
# Но с базой ничего страшного не случится. Хотя в таком "бэкапе" может и фигня получится. 

$rar_bin a -r -rr5 -dh -mdG -ep1 -ol -ow etc.rar /etc
$rar_bin a -r -rr5 -dh -mdG -ep1 -ol -ow home.rar /home
sync

echo 'Make crypted archives ...';
gpg --homedir $gpgdir -e -r $gpgkey -o 1c_postgre_compressed.swp $gpgzip 1c_postgre_compressed.bak
gpg --homedir $gpgdir -e -r $gpgkey -o postgre_sysdb_compressed.swp $gpgzip postgre_sysdb_compressed.bak
gpg --homedir $gpgdir -e -r $gpgkey -o 1c_postgre_sql_dump.swp $gpgzip 1c_postgre_sql_dump.gz
gpg --homedir $gpgdir -e -r $gpgkey -o postgre_sysdb_sql_dump.swp $gpgzip postgre_sysdb_sql_dump.gz
gpg --homedir $gpgdir -e -r $gpgkey -o buh_files.swp $gpgzip buh_files.rar
gpg --homedir $gpgdir -e -r $gpgkey -o manager_files.swp $gpgzip manager_files.rar
#gpg --homedir $gpgdir -e -r $gpgkey -o _mysql_db.swp $gpgzip _mysql_db.rar # Бэкапить MySQL прямым копированием - зело =)
gpg --homedir $gpgdir -e -r $gpgkey -o _mysql_sql_dump.swp $gpgzip _mysql_sql_dump.gz
gpg --homedir $gpgdir -e -r $gpgkey -o etc.swp $gpgzip etc.rar
gpg --homedir $gpgdir -e -r $gpgkey -o home.swp $gpgzip home.rar
#gpg --homedir $gpgdir -e -r $gpgkey -o 1c_dt.swp $gpgzip 1C.dt # Пока не работает.
sync

echo 'Move crypted archives ...';
mv $dir_open/$date/*.swp $dir_crypt/$date
sync

echo 'Delete old backups ...';
# Тут есть одна шняга. От старых бэкапов остаются пустые каталоги. То есть файлы внутри каталогов со старыми бэкапами сносятся, а сами каталоги - нет.
# Надо как-нить побороть лень и сделать более изящно. Срок хранения зашифрованных и незашифрованных бэкапов разный !!
find $dir_open/ -mtime +$days_open_store -delete                                # Удалим все устаревшие незашифрованные бэкапы
find $dir_crypt/ -mtime +$days_crypt_store -delete                        # Удалим все устаревшие зашифрованные бэкапы

echo "=== BackUp script complete ===== [$date]";

10

Тут попробовал сделать скрипт архивирования по учебнику. Такого содержания:

 Консоль:
#!/bin/bash
backup_dir1=myhome_directory_$(date +%Y-%m-%d).tar.gz
backup_dir2=/home/shared/public/
tar -czf $backup_dir2 $backup_dir1

Выдает ошибку:

 Консоль:
tar: myhome_directory_2011-02-27.tar.gz: Функция stat завершилась с ошибкой: Нет такого файла или каталога
tar: /home/shared/public/: Функция open завершилась с ошибкой: Это каталог
tar: Неисправимая ошибка: завершение работы
tar: Child returned status 2
tar: Завершение работы с состоянием неисправности с из-за возникших ошибок

Что сделал неправильно?

11

Nigelist пишет:

Тут попробовал сделать скрипт архивирования по учебнику. Такого содержания:

 Консоль:
#!/bin/bash
backup_dir1=myhome_directory_$(date +%Y-%m-%d).tar.gz
backup_dir2=/home/shared/public/
tar -czf $backup_dir2 $backup_dir1

Выдает ошибку:

 Консоль:
tar: myhome_directory_2011-02-27.tar.gz: Функция stat завершилась с ошибкой: Нет такого файла или каталога
tar: /home/shared/public/: Функция open завершилась с ошибкой: Это каталог
tar: Неисправимая ошибка: завершение работы
tar: Child returned status 2
tar: Завершение работы с состоянием неисправности с из-за возникших ошибок

Что сделал неправильно?

 Консоль:
#!/bin/bash
backup_dir1=myhome_directory_$(date +%Y-%m-%d).tar.gz
backup_dir2=/home/shared/public/
tar -czf $backup_dir1 $backup_dir2

Так попробуйте.

12

Nigelist пишет:

Тут попробовал сделать скрипт архивирования по учебнику. Такого содержания:

выкиньте свой учебник на помойку.
читайте это.

Nigelist пишет:

Добрый день! Пока не умею писать скрипты. В общем передо мной стоит задача - настроить бэкап БД постгреса со следующими параметрами:

1    *      чтобы бэкап имел максимально сжатие
2    *      Кол-во хранимых бэкапов в определенном каталоге не превышал определенного кол-ва
3    *      Имя бэкапа задавалось исходя из текущей даты, например: - postgres_YYYY-MM-DD

Может кто поможет с этим делом?

1) man xz
2) man ls, man head
3) man date

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

13

drBatty пишет:

выкиньте свой учебник на помойку.
читайте это.

drBatty, я имел в виду статью на этой странице... smile
Эта книга нормальная?

14

Nigelist пишет:

я имел в виду статью на этой странице...

ладно, оставим нужную trow на совести Кузнецова ab

Nigelist пишет:

Эта книга нормальная?

я про неё и говорил.
а вообще вам нужно man tar && info tar
читать (что такое && знаете уже?)

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

15

drBatty пишет:

читать (что такое && знаете уже?)

Ага знаю. Еще не спец, но уже не чайник... smile

16

Нужно написать скрипт, который будет делать бэкап. Исходя из примеров вот написал. Где я ошибся? ab

#!/bin/bash
if [(-d $"/srv/backup") -eq 0]
    mdir /srv/backup
fi

cd /srv/backup
tar -cvf $(date +%Y-%m-%d).tar.gz /srv/firma1 /srv/firma2 /srv/firma3 

17 (07.06.2012 15:18:32 отредактировано bormant)

Ошибки:
[(-d, mdir, пропущен then

Можно проще:

#!/bin/bash

mkdir /srv/backup 2> /dev/null
cd /srv/backup
tar -cvf $(date +%Y-%m-%d).tar.gz /srv/firma1 /srv/firma2 /srv/firma3

18

mkdir /srv/backup 2> /dev/null

А можеш объяснить эту строчку, что означает 2> и   dev здесь в виде оператора ?  ah

19

Читать "man bash" на предмет перенаправления вывода.
2> -- перенаправление второго канала (stderr), куда выводятся ошибки. /dev/null -- устройство, всегда готовое к приёму данных, отправленные туда данные уходят "в никуда".

Если этого не сделать, mkdir будет ругаться в консоль на существующий каталог /srv/backup. В приведённом примере эта ругань отправляется в /dev/null и не раздражает пользователя.

20 (07.06.2012 15:35:05 отредактировано bormant)

Первоначальный вариант был бы таким (пробелы важны):

#!/bin/bash

BACKUP=/srv/backup

if [ ! -d $BACKUP ]; then
    mkdir $BACKUP
fi
cd $BACKUP
tar zcvf $(date +%Y-%m-%d).tar.gz /srv/firma1 /srv/firma2 /srv/firma3 

21

Большое спасибо. И ещё тогда ворос, скрипт не запускаеться, пишет Permission denied. Хотя я нахожусь под рутом. Или в скрипте это нужно где-то указать?

22 (07.06.2012 15:40:16 отредактировано yars)

 Консоль: root
[root@linuxforum.ru ~]# chmod ug+x file.sh
[root@linuxforum.ru ~]#./file.sh

Истинный hotplug - это обычная электрическая розетка: воткнул - работает, и никаких драйверов.
Arch Linux/Xfce/Xiaomi Mi Notebook Pro 15.6 | Slackware64-current/Xfce/Lenovo G580

23 (07.06.2012 15:39:12 отредактировано bormant)

Если выполните "ls -l", увидите, что права на исполнение (x) нет. Нужно выдать:

# chmod +x имя_скрипта

Кроме того, у рута текущий каталог отсутствует в $PATH, поэтому, если запускать из текущего каталога, то не забыть указание пути (в примере ниже -- относительного):

./имя_скрипта

Или добавить в один из каталогов, перечисленных в $PATH.

24

Можно просто:

# bash имя_скрипта
История показывает, что во всем новом обычно кроется какой-то подвох.
Классическая ошибка, которую совершают проектировщики
абсолютно надежных систем, - недооценка изобретательности клинических идиотов.

25

Работает ab Всмем спасбо  bi  bi

26

Тоже всё получилось, заработало на УРА!

27 (28.10.2012 04:34:18 отредактировано Shark-kun)

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

forkostya пишет:

15) Оператор выбора - Case

#!/bin/bash
echo "What is your preferred programming / scripting language"
echo "1) bash"
echo "2) perl"
echo "3) phyton"
echo "4) c++"
echo "5) I do not know !"
read case;
# простая структура case-выбора
# обратите внимание, что в данном примере $case - всего лишь переменная
# и не обязана так называться. Это лишь пример
case $case in
    1) echo "You selected bash";;
    2) echo "You selected perl";;
    3) echo "You selected phyton";;
    4) echo "You selected c++";;
    5) exit
esac

$ ./case.sh
What is your preferred programming / scripting language
1) bash
2) perl
3) phyton
4) c++
5) I do not know !
4
You selected c++

Всём спасибо! сам разобрался, остановился на скрипте который выше...

Up: как сделать чтобы водной из этих функций можно было скажем путь указат
пример:

#!/bin/bash
echo "other"
echo "1) Copy as.."
echo "2) Auto copy to profile"
echo "0) Closed"
read case;
case $case in
    1) cp test.txt <указать путь самому> echo "Please enter path:" ;;
    2) cp test.txt /home/user ;;
    0) exit
esac
$ ./test.sh
other
1) Copy as.
2) Auto copy to profile
0) Closed
1
Please enter path:
/var/www

28

Shark-kun пишет:

case $case in

Использование в качестве имени переменной названия оператора оболочки — плохая привычка.

Shark-kun пишет:

Up: как сделать чтобы водной из этих функций можно было скажем путь указат

Использовать read внутри одного из пунктов выбора конструкции case, чтобы получить данные о пути от пользователя.

Был, был и весь вышел...

29 (28.10.2012 18:44:35 отредактировано Shark-kun)

можно на примере, пока не понимаю как его использовать?!

Up: Спасибо за подсказку, разобрался...
Рабочий пример:

#!/bin/bash
echo "Install BF2CCD"
echo "1) Install 'Note: installing mono required to run BF2CCD!'"
echo "0) Cancel"
read case;
case $case in
    1) echo "Please enter path install BF2CCD:"
    read key
    cp BDSoft.BF2.Server.dll bf2ccd.exe $key ;;
    0) exit
esac