BASH Scripting

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

H1ghlander
Сообщения: 8

Re: BASH Scripting

Сообщение H1ghlander »

по-моему мы говорим немного о разных вещах.
главное, что я хочу добиться это как бы временное хранилище кое-каких данных, которые бы обновляли через какой-то период времени.
Опишу ситуацию целиком: пишу скрипт для коньков, о мониторинге заряда батареи, все что надо уже сделал, осталось вывести на сколько времени хватит еще аккумулятора.
данные о оставшемся времени беру с помощью acpi. cut забираю нужную часть и все вроде бы ничего, скрипт работает, но возникла одна проблема. программа acpi иногда немного притормаживает и ее выполнение занимает примерно 1 сек. и когда конки обновляются скрипт до конца не успевает сработать из-за acpi и оставшееся время просто не отображается.
Вот и хочу сделать в скрипте так называемое хранилище, в самом бы скрипте выполнялось обновление данных acpi допустим каждые 30 сек. и куда-нибудь заносились и на конки данные брались бы уже от туда.
Вот как смог так и объяснил))
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: BASH Scripting

Сообщение diesel »

H1ghlander писал(а):
12.01.2009 22:05
по-моему мы говорим немного о разных вещах.
главное, что я хочу добиться это как бы временное хранилище кое-каких данных, которые бы обновляли через какой-то период времени.
Опишу ситуацию целиком: пишу скрипт для коньков, о мониторинге заряда батареи, все что надо уже сделал, осталось вывести на сколько времени хватит еще аккумулятора.
данные о оставшемся времени беру с помощью acpi. cut забираю нужную часть и все вроде бы ничего, скрипт работает, но возникла одна проблема. программа acpi иногда немного притормаживает и ее выполнение занимает примерно 1 сек. и когда конки обновляются скрипт до конца не успевает сработать из-за acpi и оставшееся время просто не отображается.
Вот и хочу сделать в скрипте так называемое хранилище, в самом бы скрипте выполнялось обновление данных acpi допустим каждые 30 сек. и куда-нибудь заносились и на конки данные брались бы уже от туда.
Вот как смог так и объяснил))

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

как вариант бесконечному циклу: crontab
Спасибо сказали:
Аватара пользователя
Folderx
Сообщения: 296
ОС: fedora, mandriva

Re: BASH Scripting

Сообщение Folderx »

H1ghlander писал(а):
12.01.2009 18:08
diesel
спасибо.

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


Код: Выделить всё

[guest@localhost ~]$ cd tmp
[guest@localhost tmp]$ ls
1  code  for_funcs  kdialog.txt  music  q  save  site
[guest@localhost tmp]$ declare -f Time
Time ()
{
    date +%H:%M:%S;
    return 0
}
[guest@localhost tmp]$ while sleep 5; do Time >> time.today; done &
[1] 3959
[guest@localhost tmp]$ ls
1  code  for_funcs  kdialog.txt  music  q  save  site  time.today
[guest@localhost tmp]$ cat time.today
10:58:51
10:59:13
10:59:18
10:59:23
[guest@localhost tmp]$ cat time.today
10:58:51
10:59:13
10:59:18
10:59:23
10:59:28
10:59:33
10:59:38
10:59:43
10:59:48
10:59:51
10:59:53
10:59:58
[guest@localhost tmp]$

работает пока запущена консоль в которой цикл, т.е. при старте системы можно запускать скрипт
Спасибо сказали:
Strik
Сообщения: 13

Re: BASH Scripting

Сообщение Strik »

Здравствуйте!

Нигде не нашёл никакой информации, возможно ли перевести вывод команды (>>) не в конец файла, а в начало? Подскажите пожалуйста как это можно сделать.
Спасибо сказали:
Аватара пользователя
randomize
Сообщения: 174
Статус: MegaBizon
ОС: Calculate Linux 10.4

Re: BASH Scripting

Сообщение randomize »

никак, априори ДОПИСЫВАЕТ в конец файла
Don't spit on my mind
Спасибо сказали:
Аватара пользователя
NekoExMachina
Сообщения: 485
ОС: Кошерная.

Re: BASH Scripting

Сообщение NekoExMachina »

Strik
Как это точно сделать, не знаю, но есть пакет moreutils, в котором есть программка sponge.
С ее помощью можно сделать так:
cat file | <обрабатываем awk'ом,например, нужным образом текст, вставляя в начало строку/вывод программы/etc> | sponge file
Может быть, поможет.
Ну или можно пойти окружным путем - просто два файла с последующим mv.
На форуме больше не появляюсь.
Высокопарность и надменность довела.
OpenBSD-current+scrotwm*1 (acer aspire one 531h)
FreeBSD 8.1+kde3*1 (desktop)
FreeBSD 8.1+scrotwm*1 (hp530)
FreeBSD 9.0+dwm*1 (old toshiba satellite)

Спасибо сказали:
Strik
Сообщения: 13

Re: BASH Scripting

Сообщение Strik »

Спасибо, посмотрю...
Спасибо сказали:
Аватара пользователя
NekoExMachina
Сообщения: 485
ОС: Кошерная.

Re: BASH Scripting

Сообщение NekoExMachina »

Гм. Вот такой вот вопрос меня мучает. Есть некоторое слово, его надо гренуть из текстового файла. Соответственно grep word file. А можно ли как-нибудь грепнуть вместе со строкой с этим словом еще n строк вниз-вверх от нее?
(содержимое строк неизвестно, т.е. grep -E 'word|word2' не годится)
На форуме больше не появляюсь.
Высокопарность и надменность довела.
OpenBSD-current+scrotwm*1 (acer aspire one 531h)
FreeBSD 8.1+kde3*1 (desktop)
FreeBSD 8.1+scrotwm*1 (hp530)
FreeBSD 9.0+dwm*1 (old toshiba satellite)

Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: BASH Scripting

Сообщение pcodr »

NekoExMachina
А man grep не смотрели?

-A NUM, --after-context=NUM
-B NUM, --before-context=NUM
remote system type is unix
Спасибо сказали:
Аватара пользователя
NekoExMachina
Сообщения: 485
ОС: Кошерная.

Re: BASH Scripting

Сообщение NekoExMachina »

Ой. Дико извиняюсь.
На форуме больше не появляюсь.
Высокопарность и надменность довела.
OpenBSD-current+scrotwm*1 (acer aspire one 531h)
FreeBSD 8.1+kde3*1 (desktop)
FreeBSD 8.1+scrotwm*1 (hp530)
FreeBSD 9.0+dwm*1 (old toshiba satellite)

Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: BASH Scripting

Сообщение Portnov »

Более того, там же есть ещё и "-C NUM" - смотрит в обе стороны.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
Аватара пользователя
BURF
Сообщения: 479
Статус: ZONGO!
ОС: openSUSE 12.1 x64

Re: BASH Scripting

Сообщение BURF »

А насколько важно название скрипта? А то у меня ээ скрипт, допустим, gms работает, а при сохраннии его же с названием gms4 пишет "Отказано в доступе"... и под рутом тоже. Оба лежат в ~/bin

ээ, у меня не bash скрипт.. но от этого может быть разница? там вверху #!/bin/sh ...

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

аа ээ там просто запуск как программы не стоял... сам дур
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: BASH Scripting

Сообщение pcodr »

Как в баше по человечески разбить текст например на массив по определенному сепаратору.
В частности мне нужно разбить текст по тройному переносу строк, т.е сепаратор равен \n\n\n
Пытался сделать с помощью спец переменной IFS так:

Код: Выделить всё

IFS=$'\n\n\n'
array=( $text )
echo ${array[0]}


Но так ничего не вышло почемуто, хотя с другими видами разделителей (не тройным переносом строк) так работает.
Как правильно?
remote system type is unix
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: BASH Scripting

Сообщение diesel »

pcodr писал(а):
03.02.2009 09:54
Как в баше по человечески разбить текст например на массив по определенному сепаратору.
В частности мне нужно разбить текст по тройному переносу строк, т.е сепаратор равен \n\n\n
Пытался сделать с помощью спец переменной IFS так:

Код: Выделить всё

IFS=$'\n\n\n'
array=( $text )
echo ${array[0]}


Но так ничего не вышло почемуто, хотя с другими видами разделителей (не тройным переносом строк) так работает.
Как правильно?

если IFS - Field Separator(В строке) - три переноса строки, а разделитель строк - один перенос строки. Не порядок..... Что строки должно разделять, если разделитель полей - три переноса?
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: BASH Scripting

Сообщение pcodr »

diesel писал(а):
03.02.2009 11:47
если IFS - Field Separator(В строке) - три переноса строки, а разделитель строк - один перенос строки. Не порядок..... Что строки должно разделять, если разделитель полей - три переноса?


А разделитель строк какой переменной представлен?
Может быть с помощью awk получится лучше?
Так ведь тоже не выходит:
echo "`top -bn 3`" | awk '{split($0, a, "\n\n\n"); print a[3]}'
Похоже awk вообще не понимает символа \n. Как сделать?

Да мне нужно именно получить последнюю (из 3-x) итерацию вывода команды top.
remote system type is unix
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: BASH Scripting

Сообщение ZyX »

pcodr писал(а):
03.02.2009 14:28
А разделитель строк какой переменной представлен?
Может быть с помощью awk получится лучше?
Так ведь тоже не выходит:
echo "`top -bn 3`" | awk '{split($0, a, "\n\n\n"); print a[3]}'
Похоже awk вообще не понимает символа \n. Как сделать?

Да мне нужно именно получить последнюю (из 3-x) итерацию вывода команды top.

Код: Выделить всё

(zyx:~) % top -bn 3 >topex.txt
(zyx:~) % <topex.txt | perl -e "my @arr=split(/\\n{3}/, join(\"\", <>)); print(\$arr[2]);"
top - 18:31:02 up 1 day, 21:24,  1 user,  load average: 0.40, 0.61, 0.61
Tasks: 145 total,   1 running, 144 sleeping,   0 stopped,   0 zombie
Cpu(s):  7.5%us,  3.7%sy,  0.0%ni, 81.3%id,  7.3%wa,  0.0%hi,  0.2%si,  0.0%st
Mem:   1032000k total,  1008636k used,    23364k free,     4756k buffers
Swap:  5245140k total,   332936k used,  4912204k free,   365116k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
<…>

Как сделать это нормально и без perl, я не знаю. Но вот другой пример (на zsh):

Код: Выделить всё

(zyx:~) % COUNT=1; EMPTYLINES=1; <topex.txt|while read i; do if (( COUNT==3 )); then echo "$i"; fi; if [[ -z "$i" ]]; then (( EMPTYLINES++ )); else EMPTYLINES=1; fi; if (( EMPTYLINES==3 )); then (( COUNT++ )); fi; done
top - 18:31:02 up 1 day, 21:24,  1 user,  load average: 0.40, 0.61, 0.61
Tasks: 145 total,   1 running, 144 sleeping,   0 stopped,   0 zombie
Cpu(s):  7.5%us,  3.7%sy,  0.0%ni, 81.3%id,  7.3%wa,  0.0%hi,  0.2%si,  0.0%st
Mem:   1032000k total,  1008636k used,    23364k free,     4756k buffers
Swap:  5245140k total,   332936k used,  4912204k free,   365116k cached

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
<…>

Жуткая конструкция, не правда ли? Кроме того, read сжирает пробелы в начале
строки.

PS: Если в начале дописать ещё и «IFS="\n"», то read перестанет
жрать пробелы.

PPS: В моём bash всё работает точно так же, достаточно заменить
конструкцию „<topex.txt” на «cat topex.txt».
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: BASH Scripting

Сообщение pcodr »

ZyX
Спасибо за содействие, но на perl я уже сам сделал так

Код: Выделить всё

top -bn 3 | perl -e 'print((split("\n\n\n", join("", <>)))[2])'

Хоть и однострочник, не люблю использовать perl в баше, все время возникает ощущение что можно было писать весь скрипт на перле :)
Ну ладно остановлюсь на нем, раз проще не сделать.
remote system type is unix
Спасибо сказали:
H1ghlander
Сообщения: 8

Re: BASH Scripting

Сообщение H1ghlander »

как лучше написать скрипт, который бы два раза с интервалом в 30 секунд проверял запущено ли приложение или нет. И если приложение не запущено - выполнялось бы действие.
Мне хотя бы все в общих чертах, а дальше я сам разберусь.
Спасибо сказали:
varjo
Сообщения: 43
ОС: ArchLinux, FreeBSD

Re: BASH Scripting

Сообщение varjo »

H1ghlander писал(а):
19.02.2009 18:12
как лучше написать скрипт, который бы два раза с интервалом в 30 секунд проверял запущено ли приложение или нет. И если приложение не запущено - выполнялось бы действие.
Мне хотя бы все в общих чертах, а дальше я сам разберусь.

cron, ps, grep
Спасибо сказали:
H1ghlander
Сообщения: 8

Re: BASH Scripting

Сообщение H1ghlander »

varjo писал(а):
19.02.2009 20:43
H1ghlander писал(а):
19.02.2009 18:12
как лучше написать скрипт, который бы два раза с интервалом в 30 секунд проверял запущено ли приложение или нет. И если приложение не запущено - выполнялось бы действие.
Мне хотя бы все в общих чертах, а дальше я сам разберусь.

cron, ps, grep

это я и без вас знал, нужно чуть-чуть более поподробнее :rolleyes:
Спасибо сказали:
varjo
Сообщения: 43
ОС: ArchLinux, FreeBSD

Re: BASH Scripting

Сообщение varjo »

H1ghlander писал(а):
19.02.2009 20:47
varjo писал(а):
19.02.2009 20:43
H1ghlander писал(а):
19.02.2009 18:12
как лучше написать скрипт, который бы два раза с интервалом в 30 секунд проверял запущено ли приложение или нет. И если приложение не запущено - выполнялось бы действие.
Мне хотя бы все в общих чертах, а дальше я сам разберусь.

cron, ps, grep

это я и без вас знал, нужно чуть-чуть более поподробнее :rolleyes:

count=$(ps x | grep ИМЯ_ПРОЦЕССА | grep -vc grep)
if ($count -eq 0) then
ДЕЙСТВИЕ
fi
sleep 30
..и еще раз тоже самое
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: BASH Scripting

Сообщение diesel »

varjo писал(а):
19.02.2009 23:22
H1ghlander писал(а):
19.02.2009 20:47
varjo писал(а):
19.02.2009 20:43
H1ghlander писал(а):
19.02.2009 18:12
как лучше написать скрипт, который бы два раза с интервалом в 30 секунд проверял запущено ли приложение или нет. И если приложение не запущено - выполнялось бы действие.
Мне хотя бы все в общих чертах, а дальше я сам разберусь.

cron, ps, grep

это я и без вас знал, нужно чуть-чуть более поподробнее :rolleyes:

count=$(ps x | grep ИМЯ_ПРОЦЕССА | grep -vc grep)
if ($count -eq 0) then
ДЕЙСТВИЕ
fi
sleep 30
..и еще раз тоже самое


в Linux есть pgrep ... кажется можно просто
if pgrep ИМЯ_ПРОЦЕССА > /dev/null; then
ДЕЙСТВИе
fi

if ($count -eq 0) then не совсем верно: if [ $count -eq 0 ]; then


pcodr писал(а):
03.02.2009 14:28
diesel писал(а):
03.02.2009 11:47
если IFS - Field Separator(В строке) - три переноса строки, а разделитель строк - один перенос строки. Не порядок..... Что строки должно разделять, если разделитель полей - три переноса?


А разделитель строк какой переменной представлен?
Может быть с помощью awk получится лучше?
Так ведь тоже не выходит:
echo "`top -bn 3`" | awk '{split($0, a, "\n\n\n"); print a[3]}'
Похоже awk вообще не понимает символа \n. Как сделать?

Да мне нужно именно получить последнюю (из 3-x) итерацию вывода команды top.

пардон не заметил сразу. для awk вы можете использовать переменные FS, RS
FS - Field Separator - разделитель полей
RS - Record Separator - разделитель строк
Задаются в блоке BEGIN. like BEGIN{RS="\n\n\n"}
http://www.in4.org.ua/2008/08/cli-as-i-use...part-2-awk.html - вот тут есть примеры этого, не хочу пересказывать.
не совсем понял правда где в top -mn3 вы нашли "\n\n\n"
Спасибо сказали:
varjo
Сообщения: 43
ОС: ArchLinux, FreeBSD

Re: BASH Scripting

Сообщение varjo »

diesel писал(а):
20.02.2009 11:48
if ($count -eq 0) then не совсем верно: if [ $count -eq 0 ]; then

точно, мой косяк, незнаю о чем думал когда писал :(
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: BASH Scripting

Сообщение pcodr »

diesel
Спасибо за информацию, учту на будущее. В top -bn 3 "\n\n\n" идут между итерациями вывода топ-листа.

H1ghlander

Код: Выделить всё

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


Узнавать запущен ли процесс лучше всего зная его pid, а не название. Если сам этот процесс не умеет создавать pid-файл можно организовать его запуск через скрипт и уже скриптом создавать pid-файл:

Код: Выделить всё

echo $$ > /var/run/process.pid
exec process

где process нужная вам программа.

Проверить запущен ли процесс зная его pid можно с помощью утилиты kill
Пример:

Код: Выделить всё

if kill -0 `cat /var/run/process.pid`
then
      echo "process running"
else
      echo "process stopped"
fi


В данном примере утилите kill указывается отослать процессу сигнал 0. Но вообще говоря при указании 0-вого сигнала никаких сигналов процессу не доставляется, а лишь проверяется возможность их доставки. В частности если процесса с указанным pid не существует, то сигнал не сможет быть доставлен, отсюда и отталкиваемся. Но нужно также учесть что сигнал не может быть доставлен если у вас нет на это прав, так что проверять таким образом следует либо запуская скрипт от суперпользователя, либо проверять только процессы от тогоже пользователя под коим запущен скрипт.
remote system type is unix
Спасибо сказали:
Аватара пользователя
Folderx
Сообщения: 296
ОС: fedora, mandriva

Re: BASH Scripting

Сообщение Folderx »

запущен ли процесс можно узнать по наличию каталога в /proc
запущена ли программа можно узнать через

Код: Выделить всё

# CheckProcess:  check running the program;
#                CheckProcess progname;
CheckProcess() {
    local TRUE=0 FALSE=1;

    if pidof "$1" 1>/dev/null; then
        return $TRUE;
    else
        return $FALSE;
    fi;
};


Код: Выделить всё

[guest@station ~]$ PROG=kmix;
[guest@station ~]$ if CheckProcess "$PROG"; then echo "$PROG" running; fi;
kmix running
[guest@station ~]$ PROG=kwrite;
[guest@station ~]$ if CheckProcess "$PROG"; then echo "$PROG" running; fi;
[guest@station ~]$
Спасибо сказали:
H1ghlander
Сообщения: 8

Re: BASH Scripting

Сообщение H1ghlander »

varjo
спасибо! я что-то сам не допер, про подсчет строк (count=$(ps x | grep ИМЯ_ПРОЦЕССА | grep -vc grep))


Сейчас мне дано сделать сортировку ip адресов.
Сейчас я пока знаю как отсортировать ip в такой вид:
192.168.1.1
192.168.1.100
192.168.1.2
192.168.1.3
192.168.1.4

А надо чтобы вид был такой:
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.100
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: BASH Scripting

Сообщение pcodr »

H1ghlander писал(а):
21.02.2009 17:42
Сейчас я пока знаю как отсортировать ip в такой вид:
192.168.1.1
192.168.1.100
192.168.1.2
192.168.1.3
192.168.1.4


Тогда что-то вроде этого. В /tmp/test.txt список айпишников отсортированных так как вы знаете.

Код: Выделить всё

while read l; do echo -n `echo "$l" | egrep -o '[0-9]+$'`; echo " $l"; done < /tmp/test.txt | sort -n | cut -d " " -f 2
remote system type is unix
Спасибо сказали:
Hast
Сообщения: 23

Re: BASH Scripting

Сообщение Hast »

Всем привет! Ребят, нужна помощ. Есть небольшой скрипт написаный на перле. Нужно реализовать его на баше. Но баш я не знаю совсем :( вот скрипт:

#!/usr/bin/perl
$date = `date`;
if ( $date =~ /^(.+?)(\d+:\d+:\d+)(.+?)$/i ) {

print "$2\n";

} else {

print "ошибка поиска\n";

}


т.е. скрипт из результата комманды date выдёргивает только Часы:минуты:секунды и выводит это на экран. Только и всего. Вобщем кому не лень помоч реализовать этот небольшой скрипт на баше - помогите пожалуйста :)

спасибо.
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: BASH Scripting

Сообщение ZyX »

Hast писал(а):
27.02.2009 22:19
Всем привет! Ребят, нужна помощ. Есть небольшой скрипт написаный на перле. Нужно реализовать его на баше. Но баш я не знаю совсем :( вот скрипт:

#!/usr/bin/perl
$date = `date`;
if ( $date =~ /^(.+?)(\d+:\d+:\d+)(.+?)$/i ) {

print "$2\n";

} else {

print "ошибка поиска\n";

}


т.е. скрипт из результата комманды date выдёргивает только Часы:минуты:секунды и выводит это на экран. Только и всего. Вобщем кому не лень помоч реализовать этот небольшой скрипт на баше - помогите пожалуйста :)

спасибо.

Абсолютно ничего выдергивать из вывода date не надо, вместо скрипта надо просто
прочитать man date:

zyx@zyx-desktop

(zyx:~) % date +"%T" 23:42:19
Спасибо сказали:
Hast
Сообщения: 23

Re: BASH Scripting

Сообщение Hast »

Мне не результат нужен а процесс :) Суть скрипта - демонстрация использования регулярных выражений на баше и перле. С перлом я знаком, а вот с башем очень плохо.
Спасибо сказали: