Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Операционные системы (2 семестр).docx
Скачиваний:
3
Добавлен:
12.11.2019
Размер:
193.38 Кб
Скачать

Хід роботи

У цій роботі Вам має бути використовувати поряд із системними утилітами алгоритмічні й обчислювальні можливості мови shell, змінні shell і параметри скрипта. Для розв'язку поставленої в індивідуальному завданні завдання Ви можете використовувати будь-які засоби системи, однак, по можливості намагайтеся уникати застосування утиліти awk. Це обмеження продиктоване число методичними цілями для ( вибачте!) навмисного ускладнення вартому перед Вами завдання.

Зверніть увагу: якщо у Вашому завданні в послу деяких параметрів коштує три крапки, те це означає, що параметрів цього виду може бути кілька.

Ваш розв'язок повинний бути оформлене у вигляді, що виконується скрипта й записане у Ваш каталог $HOME/bin, який Ви створили у включили в змінну PATH у попередній роботі. При налагодженні скрипта зверніть увагу на те, щоб скрипт коректно працював, будучи викликаним з будь-якого поточного каталогу. Ви можете створювати тимчасові файли, якщо це виявляється необхідним для розв'язку завдання (див. приклад виконання). Зверніть увагу на те, щоб скрипт не залишав тимчасових файлів.

Під час Вашої роботи в системі будуть присутні два "тестові" користувачі з іменами "ap10998" і "ap10999"; ви можете скористатися цими іменами для відправлення їм повідомлень, перевірки їх файлів і для налагодження тих завдань, параметрами яких є імена користувачів.

Деякі приклади програмування

Описані нижче деякі приймання програмування, можливо, допоможуть Вам у розв'язку Вашого завдання. У більшості випадків Вам знадобляться команди обробки текстів і потоковий редактор sed. Інформацію про файли, як правило, можна одержати від команди ls і інших команд файлової системи. Короткі описи всіх необхідних команд є в нашій довідковій системі.

Конвеєри й тимчасові файли

При розв'язку більшості завдань Вам доведеться застосовувати конвеєри команд. Не завжди, однак, вдається безпосередньо використовувати вихід однієї команди на вході іншої. Іноді потрібно підготувати два джерела даних (наприклад, для з'єднання), іноді доцільно зберегти результати виконання команди для повторного їхнього використання. У таких випадках можна зберігати результати в тимчасовому файлі.

Однак, формуючи ім'я тимчасового файлу, не забувайте про те, що Ви можете не мати прав на створення файлів у тому каталозі, який є поточним у момент виконання команди. Тому тимчасові файли доцільно створювати в домашньому каталозі користувача, що виконує скрипт. Таким чином, виконання команди з перенапрямком її результату в тимчасовий файл буде виглядати так:

команда параметри... > $HOME/tempfile

Обробка списку параметрів

Якщо у Вашому завданні передбачається обробка списку параметрів, то вона може бути виконана в такому циклі:

while [ $# -ne 0 ]

do

обробка параметра $1

shitf

done

У кожній ітерації цього циклу обробляється 1-й параметр ($1). Наприкінці циклу командою shift список параметрів зрушується, 2-й параметр стає першим і т.д. Цикл виконується доти, поки кількість параметрів у списку ($#) не стане рівним 0.  

Обробка структурованих файлів

У деяких завданнях файли складаються з текстів, організованих у рядки й стовпці. Такі ж тексти видають на виході деякі системні утиліти, наприклад, утиліта ls с опцією -l. Для обробки таких файлів зручно використовувати команди, орієнтовані на структуровані файли: виділення полів - cut, сортування - sort, реляційне з'єднання - join (не забувайте, що join вимагає, щоб файли були попередньо відсортовані!). Випливає, однак, мати на увазі, по-перше, що в цих команд різні опції завдання роздільників у тексті, і при їхнім спільному вживанні слід бути уважним щодо цього, а по-друге, те, що поля в структурованих файлах найчастіше розділяються змінним числом пробілів, а всі ці команди вимагають єдиного роздільника між полями. Тому перш ніж застосовувати до структурованого файлу таку команду, потрібно замінити множинні пробіли єдиним, що можна зробити, наприклад, таким звертанням до потокового редактора sed:

sed-n's/ */ /gp'

яка заміняє один пробіл і будь-яка кількість наступних за ним пробілів на один пробіл. (У цій команді редагування в шаблону пошуку перед символом '*' коштують два пробіли, а шаблон заміни складається з єдиного пробілу. Опція g пропонує замінити всі входження.)

Як правило, у завданнях, зв'язаних зі структурованими файлами, обробляються тільки вибрані поля файлу. Рекомендуємо Вам для полегшення своєї роботи вже на початковому етапі обробки позбутися непотрібних стовпців за допомогою команди cut

 Порядкова обробка файлів

Припустимо (типова для деяких завданнях ситуація), що нам потрібно читати деякої файл - вихідний_файл рядок за рядком і обробляти кожний рядок. Деякі з можливих варіантів такої обробки наступні:

Увести змінну - номер рядка й використовувати значення цієї змінної при формуванні шаблону пошуку для команди sed або grep:

  1. # початкове значення лічильника рядків - 1

  2. n=1

  3. # нескінченний цикл, вихід - по break

  4. while [ 1 ]

  5. do

  6. # виконується sed, операція печатки рядків,

  7. # значення змінної $s підставляється в номер рядка.

  8. # результат sed - прочитаний рядок - привласнюється

  9. # змінної value

  10. value=`sed -n ''$n'p' вихідний_файл`

  11. # якщо в value прочитався порожній рядок - вихід із циклу

  12. if [ "$value" = "" ]; then

  13. break;

  14. fi

  15. обробка $value

  16. # обчислення нового номера рядка

  17. n=`expr $n +1'

  18. done

  1. Виконувати в кожній ітерації циклу читання й обробку першого рядка файлу, а потім видаляти її з файлу:

  2. # цикл виконується поки у вихідному файлі є рядка

  3. while -s test вихідний_файл

  4. do

  5. # читається 1-я рядок і її значення привласнюється

  6. # змінної value

  7. value=`head -n1 вихідний_файл`

  8. обробка $value

  9. # видалення 1-й рядка з файлу

  10. # результат перенаправляється в тимчасовий файл, потім

  11. # вихідний_файл віддаляється, тимчасовий файл

  12. # перейменовується у вихідний_файл

  13. sed '1d' вихідний_файл > $HOME/temp1

  14. rm вихідний_файл

  15. mv $HOME/temp1 вихідний_файл

  16. done

  1. Якщо текст вихідного_файлу не містить пробілів, то можна використовувати цикл for.

  2. # список для циклу зчитується з вихідного_файлу

  3. for value in `cat вихідний_файл`

  4. do

  5. обробка $value

done

Майте на увазі, що якщо текст вихідного_файлу містить пробіли, то в кожній ітерації циклу буде зчитуватися одне слово.

 Виділення рядків за значенням у стовпці

В деяких завданнях потрібно в структурований файл обмежити тільки тими рядками, які мають певне значення в певному стовпці. Простий розв'язок можна одержати за допомогою команд sed або grep, використавши задане значення в складі шаблону:

var=шукане_значення

sed -n '/специфікації_визначальні_позицію'$var'p' файл

але в деяких випадках (якщо важко сформулювати специфікації_визначальні_позицію) може виявитися зручніше застосувати штучне приймання: записати шукане_значення в окремий файл і виконати його з'єднання з вихідним файлом:

# запис шуканого_значення в тимчасовий файл

echo "шукане_значення" >$HOME/tempfile

# сортування вихідного файлу по необхідному стовпцю

sort +позиція-1 -позиція -t'разделитель' файл | # з'єднання: 1-й файл - результат попередньої команди, у ньому

# для з'єднання береться необхідний стовпець, 2-й файл - тимчасовий

# файл, у ньому - стовпець перший і єдиний

join -j1 позиція -j2 1 -t'разделитель' - $HOME/tempfile

 Приклад 1

Завдання Перевірити, працює чи в мережі заданий користувач. Якщо так - відправити йому повідомлення по write. Якщо користувача немає в мережі або він заблокував термінал, - відправити повідомлення по mail.

Формат застосування цієї команди повинен бути:

команда користувач...

Нижче ми приводимо текст скрипта (ми назвали його ex7_1) з докладними коментарями.

#!/bin/bash2

# ============================================================== #

# Скрипт ex7_1: відправлення повідомлення/листа заданим користувачам #

# ============================================================== #

# Коментар !/bin/bash2 описує місцезнаходження командного

# інтерпретатора shell. Він допомагає системі знайти інтерпретатор,

# а також допомагає команді file визначити тип файла-скрипта.

# У більшості випадків він не є обов'язковим, але є

# "правилом гарного тону" у програмуванні.

# =======================================================

#

# Текст повідомлення/листа заноситься у файл temp01

# Зверніть увагу: тимчасовий файл розміщається в домашньому

# каталозі користувача.

echo Це тестове повідомлення > $HOME/temp01

echo для перевірки зв'язку зі скрипта. >>$HOME/temp01

echo Бажаю успіху! >>$HOME/temp01

echo ap10999 >>$HOME/temp01

# ========================================================

# Параметри команди являють собою список імен користувачів.

# Наступним оператором організує цикл, який виконується до

# тих пор, поки залишаються неопрацьовані параметри.

while [ $# -ne 0 ]

do

# ======================================================

# Значення 1-го параметра привласнюється змінної us

us=$1

# ======================================================

# Віддаляється файл temp02. Зверніть увагу: діагностика команди

# rm пригнічується (направляється в "системну корину"). Ця діагностика

# може повідомляти про те, що файлу, що віддаляється, не існує -

# вона нам не потрібна.

rm $HOME/temp02 2>/dev/null

# ======================================================

# Спроба видачі повідомлення користувачеві.

# Системне введення команди write направляється на файл temp01.

# Якщо не вдається встановити з'єднання з користувачем (користувача

# немає в системі або він заблокував свій термінал) команда write

# виводить діагностичне повідомлення (ми його пригнічуємо) і

# повертає false.

if write $us <$HOME/temp01 2>/dev/null

then

# ====================================================

# Якщо повідомлення пройшло - OK! виводимо на свій термінал

# повідомлення про цей, і - "обробка користувача" закінчена.

echo "Користувачеві $us відправлене повідомлення"

else

# ====================================================

# Якщо повідомлення не пройшло - спроба відправлення листа

# Системне введення команди mail направляється на файл temp01.

# Команда mail завжди повертає true. Вона тільки запускає

# дочірній процес sendmail, і, якщо відправлення листа не вдалося,

# це буде з'ясовано тільки в дочірньому процесі, яка видасть

# діагностику, цю діагностику перенаправляємо в тимчасовий

# файл temp02.

mail $us <$HOME/temp01 >$HOME/temp02

# ====================================================

# Очікуємо 1 сек, щоб дочірній процес встигнув записати

# у файл temp02 повідомлення про те, що лист не відправлений

sleep 1

# ====================================================

# Перевіряємо, чи їсти що-небудь у файлі temp02

if test -s $HOME/temp02

then

# ==================================================

# Якщо файл temp02 не порожній - користувач не знайдений

echo "Користувач $us не знайдений"

# ==================================================

# у цьому випадку лист попадає у файл dead.letter,

# який нам не потрібний

rm $HOME/dead.letter 2>/dev/null

else

# ==================================================

# Якщо файл temp02 порожній - лист відправлений

echo "Користувачеві $us відправлений лист"

# ====================================================

# Кінець умови if test -s $HOME/temp02

fi

# ======================================================

# Кінець умови if write $us ...

fi

# ======================================================

# Зрушення списку параметрів

shift

# ========================================================

# Кінець циклу while

done

# ========================================================

# Після виходу із циклу

# Віддаляються тимчасові файли

rm $HOME/dead.letter 2>/dev/null

rm $HOME/temp01 2>/dev/null

rm $HOME/temp02 2>/dev/null

# ======== Кінець скрипта ex7_1 ================================= #

Нижче наведений зразок виконання створеної команди:

bash2-2.05$ sh ex1_7 ap10999 ap10998 ap1097

Користувачеві ap10999 відправлене повідомлення

Користувачеві ap10998 відправлений лист

Користувач ap1097 не знайдений

bash2-2.05$