* ГЛАВА 10. Змішані прийоми *
Введення
Способи перетворення в мові shell
conv
Модулі перетворення
dtoh
dtoo
htod
htoo
Тонкості bc
otod
otoh
Прийоми мови shell для забезпечення гнучкості програм
Хитрості мови shell
Читайте уведення із клавіатури, поки перебуваєте в циклі,
приєднаному до програмному каналу
Запуск дочірньої мови shell
Рівні мови shell і уведення-висновок
Убудоване уведення
З редактором ed
З файлом a.out
C архівами мови shell
Керування статусом циклу
Фільтри й синтаксис
Недоліки/особливості програмування мовою shell
Програма для перенапрямку помилки
Некоректний код повернення
Хитрості редактора Vi
Повернення в мову shell
Підтримка Escape
Макроси
Команда "One-Liners" - малюсінька, але потужна
.
- 2
Введення
Ця книга є підсумком багаторічної роботи з підбора й
розвитку інструментальних засобів ОС UNIX. Багато речей, які не
хотілося б залишати без уваги, не вписали в контекст
попередніх глав. Це й закінчені процедури, подібні представленим
раніше, і невеликі, але дуже потужні фрагменти програм. Крім того,
висловлено деякі корисні ідеї й представлені методи обробки
загальних ситуацій мовою shell.
Способи перетворення
Оскільки комп'ютери і їхні скільки-небудь утиліти використовують при
роботі різні системи числення, часто виникає необхідність
перетворення підстав систем числення. Ці перетворення
забезпечуються добре знайомими фахівцям командами UNIX bc
(калькулятор довільної точності) і dc (яка приблизно
розшифровується як настільний калькулятор ("desk calculator")).
Більшість із існуючих можливостей або носять дуже
обмежений характер, або їх важко використовувати в ряді ситуацій,
тому буде розглянуте питання як використовувати існуючі
можливості UNIX, щоб будь-яке перетворення було як можна більше
легко здійсненним.
Назва: conv
conv Переводить числа з однієї системи числення в іншу
Призначення: Забезпечує можливість перетворення підстави системи
числення
Виклик conv
Приклад виклику:
$conv Викликати головне меню різних перетворень
2 Вибрати опцію 2 ( із шестнадцатиричной у десяткову)
FFF Увести шестнадцатиричное число FFF. На виході програми
одержимо десятковий еквівалент
Вихідний текст для функції conv
1 :
2 # @(#) conv v1.0 Перетворення підстави системи
числення, використовуючи shell Автор: Russ Sage
3
4 while :
5 do
6 echo "
7
8 Перетворення підстав
9 -і-і-і-і-і-і-і-і-і-і-і-і
10 1 - Десяткове в шестнадцатиричное
11 2 - Шестнадцатиричное в десяткове
12 3 - Десяткове у восьмеричне
13 4 - Восьмеричне в десяткове
14 5 - Восьмеричне в шестнадцатиричное
15 6 - Шестнадцатиричное у восьмеричне
16
17 enter choice (1-6, <>): \c"
18 read CHOICE
19
20 case $CHOICE in
21 "") exit;;
22 1) echo "\пвведите десяткове число (<> to exit): \c"
23 read DEC
24 if [ "$DEC" = ""]
25 then exit
26 fi
27 HEX='. dtoh'
28 echo "\n${DEC}d = ${HEX}x";;
29 2) echo"\nвведите шестнадцатиричное число
у верхньому регістрі (<> to exit): \c"
30 read HEX
31 if [ "$HEX" = ""]
32 then exit
33 fi
34 DEC='. htod'
35 echo "\n${HEX}x= ${DEC}d;;
36 3) echo "\nвведите десяткове число в
верхньому регістрі (<> to exit): \c"
37 read DEC
38 if [ "$DEC" = ""]
39 then exit
40 fi
41 OCT='. dtoo'
42 echo "\n${DEC}d = ${OCT}o";;
43 4) echo "\nвведите восьмеричне число
(<> to exit): \c"
44 read OCT
45 if [ "$OCT" = ""]
46 then exit
47 fi
48 OCT='. otod'
49 echo "\n${OCT}o = ${DEC}d";;
50 5) echo "\nвведите восьмеричне число
(<> to exit): \c"
51 read OCT
52 if [ "$OCT" = ""]
53 then exit
54 fi
55 HEX='. otoh'
56 echo "\n${OCT}o = ${HEX}x";;
57 6) echo "\nвведите шестнадцатиричное число
у верхньому регістрі (<> to exit): \c"
58 read НЕХ
59 if [ "$НЕХ" = ""]
60 then exit
61 fi
62 OCT='. htoo'
63 echo "\n${HEX}x = ${OCT}o";;
64 *) echo "\n$ CHOICE-Невідома команда";;
65 esac
66 done
Змінні оточення
CHOICE - Вибір команд із головного меню
DEC - Видає десяткове значення як результат
перетворення
HEX - Видає шестнадцатиричное значення як
- 4
результат перетворення
OCT - Видає восьмеричне значення як
результат перетворення
Опис
Навіщо нам потрібна функція conv ?
Виконання числових операцій великого обсягу в командних файлах
мови shell - це далеко не сама гарна ідея. Командні файли являются досить повільними самі по собі, а виконання математичних операцій ще більше сповільнює їхню роботу. Однак, процедури мови shell
мають математичні можливості, і Ви, можливо, захочете ними
скористатися. Якщо Вам потрібно перетворити кілька чисел у процессе написання програми, то для цієї мети досить зручно викликати
процедуру мови shell. Оскільки conv - це програма, керована
меню, Вам не прийде турбуватися про запам'ятовування складного синтаксису,
котрый використовують деякі системні утиліти перетворення.
Що робить conv?
Цей інструментальний засіб забезпечує можливість перекладу
чисел з однієї системи числення в іншу. Можна переводити
десяткові, шестнадцатиричные й восьмеричні дані. Число,
записане в одній із цих форм, може бути переведене в кожну з
двох форм, що залишилися.
Режим роботи програми вибирається з головного меню. У меню є
шість пунктів. Після того як Ви вибираєте число між 1 і 6,
програма просить Вас увести число яке Ви хочете перетворити.
Відбувається перетворення й на виході програми Ви одержуєте два
значення - число, що Ви перетворюєте й число, до якого воно
було перетворено. Перетворення здійснюються шляхом виклику
зовнішніх процедур, про які буде йти мова далі в цій главі, так
що перед запуском conv необхідно переконатися, що Ви включили їх в
вашу систему й розмістили в тім же каталозі, що й conv.
Якщо Ви введете команду, що не ввійшла у вищезгаданий перелік,
те буде видане повідомлення про помилку й знову буде виведене головне
меню.
Пояснення
Рядка 4-66 - це один великий нескінченний цикл while. Ми
використовуємо нескінченний цикл, щоб у випадку помилкового уведення
програма повернулася в головне меню для повторного уведення. Для того,
щоб вийти із програми, потрібно перервати цикл, тобто вийти із циклу.
Рядка 6-17 друкують меню й видають підказку для вибору. Якщо Ви
просто натиснете "Уведення", програма завершить свою роботу.
Рядок 18 читає уведення із клавіатури, і рядка 20-65 виконують
вибір за умовою для цієї величини. Якщо отримано нульовий (порожній)
уведення, то програма завершує свою роботу.
Рядка 22-28 здійснюють переклад чисел з десяткової в
шестнадцатиричную системи числення. Оскільки всі модулі перекладу
відповідають тому самому зразку, те детально ми розглянемо тільки
даний модуль.
Підказка запитує число в рядку 23. У рядках 24-26
перевіряється, чи не було уведене значення порожнім. Рядок 27 виглядає
трохи загадково, викликаючи один із зовнішніх командних файлів dtoh
для перетворення десяткових чисел у шестнадцатииричные. Звернете
увага на те як одна програма виконує іншу.
Командний файл dtoh запускається, використовуючи команду ".". Це
означає : "Виконаєте програму, використовуючи той же shell". Процедура
dtoh використовує змінну DEC для уведення числа й видає
- 5 перетворене число на стандартний висновок. Щоб записати це число
у змінну, ми робимо присвоєння, потім запускаємо програму,
використовуючи командну підстановку. Рядок 28 видає на екран
первісне десяткове число й шестнадцатиричное, до якого воно
було перетворено.
Варіанти 2, 3, 4, 5 і 6 працюють аналогічно. Єдине, що
міняється - це ім'я змінної, котре відповідає типу
перетворення й назва командного файлу (скрипта), що
викликається для цього перетворення.
Модулі перетворення
Тепер давайте розглянемо окремо кожний з модулів перекладу.
Ці модулі або командні файли мови shell використовують команду UNIX
bc, щоб здійснювати перетворення підстав систем числення.
Не можна сказати, що команда bc - це найбільш простий і зручний
спосіб перекладу, але проте вона працює, і єдине, що
нам потрібно, - це вивчити її й помістити в командний файл.
Назва : dtoh
dtoh Десяткові в шестнадцатиричные.
Призначення: Перетворює вхідні десяткові числа у вихідні
шестнадцатиричные числа.
Синтаксис: $DEC="decimal_number"; HEX='.dtoh'
Приклад виклику
$DEC="25";HEX='.dtoh'
$echo $HEX
Привласнити DEC початкове значення 25, викликати dtoh для його
перетворення й записати результат в HEX. Вивести результати на
екран.
Вихідний текст для dtoh
1 :
2 # @(#) dtoh v1.0 Перетворення мови shell--десяткові в
шестнадцатиричные Автор: Russ Sage
3
4 bc <
Опис
Навіщо нам потрібний dtoh ?
Ця процедура перетворює десяткове число в
шестнадцатиричное - простий варіант перетворення, що нам може
знадобитися.
Що робить dtoh?
- 6
Dtoh виконує перетворення десяткових у шестнадцатиричные,
використовуючи існуюче базове перетворення, що UNIX
забезпечує за допомогою команди bc. Маніпулюючи уведенням і висновком
команди bc, ми можемо використовувати її можливості перетворення.
Пояснення
Технологія, по якій все це відбувається, досить проста. Метод
виконання - використовуючи команду мови shell ".". Це означає использовать той же shell для запуску команди, а не дочірній. Коли команда
виконується цією же мовою shell, всі змінні, які в даний
момент мають якісь значення, доступні для командного файлу dtoh.
Ми використовуємо цю перевагу й припускаємо для dtoh, що Ви правільно встановили змінної мови shell.
Рядок 4 викликає команду bc, що представляє із себе
калькулятор самого нижнього рівня. За замовчуванням bc використовує
десяткове уведення й висновок. Ми встановлюємо підставу виходу в 16 в
рядку 5. Це означає, що будь-яке число, що ми друкуємо із цього
моменту, друкується як шестнадцатиричное число.
Рядок 6 уводить десяткове число для bc, розширюючи його значення
як уведення для bс. Bc видає на екран число, записане в
шестнадцатиричной системі числення. Ми перетворили число.
Єдине, що залишилося зробити - це помістити результат в
змінної мови shell у зухвалій програмі. Але це вже зроблено в
зухвалій програмі завдяки способу виклику процедури. Преобразование відбувається усередині bc.
Дослідження
Зухвалий синтаксис - це не єдиний спосіб використовувати
ті ж самі програми. Це простіше всього, але існують і інші
способи.
У наведеній нижче програмі, використовується інший метод виклику.
Замість командної підстановки тут використовується дочірній shell,
стандартний висновок якого перенаправляється. Зверніть увагу, що
результат записується у файл, а не в змінної мови shell. Запис
у файл може виявитися корисної, якщо ті ж самі дані знадобляться
іншим програмам або якщо Ви хочете їх використовувати після закінчення
роботи програми.
$ DEC="150"; (. .dtoh) > HEX
$ echo "шестнадцатиричное число: 'cat HEX'"
Позначення () запускає викликувану процедуру в дочірньому
мові shell. Використовуючи "." для її виконання, ми по колишньому маємо
доступ до змінного DEC. Стандартний висновок перенаправляється в HEX.
Луна супровід одержує значення, використовуючи командну підстановку.
Результат cat міститься в луну пропозиція.
Назва: dtoo
dtoo Десяткові у восьмеричні
Призначення Переводить вхідні десяткові числа у вихідні
восьмеричні.
Синтаксис: DEC="decimal_number"; OCT='.dtoo'
Приклад виклику
$DEC="16";OCT='.dtoo'
- 7
$echo $OCT
Привласнити DEC початкове значення 16, викликати dtoo для її
перетворення й записати результат в OCT. Вивести результати на
екран.
Вихідний текст для dtoo
1 :
2 # @(#) dtoo v1.0 Перетворення мови shell--десяткові в
восьмеричні Автор: Russ Sage
bc < obase = 8
$DEC
!
Опис
Оскільки це й наступні засоби реобразования працюють
аналогічно dtoh, крім представляється специфики, що, перетворення, ми
опускаємо детальні пояснення.
Назва: htod
htod Шестнадцатиричные в десяткові
Призначення Переводить вхідні шестнадцатиричные числа у вихідні
десяткові.
Синтаксис: HEX="hex_number"; DEC='.htod'
Приклад виклику
$HEX="1EAC" ; DEC='.htod'
$echo $DEC
Привласнити HEX шестнадцатиричное значення, перетворити його,
надрукувати результати.
Вихідний текст для htod
1 :
2 # @(#) dtoo v1.0 Перетворення мови shell--шестнадцатиричные
у десяткові Автор: Russ Sage
bc < ibase = 16
$HEX
!
Назва: htoo
htoo Шестнадцатиричные у восьмеричні
Призначення Переводить вхідні шестнадцатиричные числа у вихідні
восмеричные.
Синтаксис: HEX="hex_number"; OCT ='.htoo'
- 8
Приклад виклику
$HEX="F1E" ;
$OCT='.htoo'
$echo $OCT
Привласнити HEX шестнадцатиричное значення, перетворити його,
надрукувати восьмеричне число.
Вихідний текст для htoo
1 :
2 # @(#) htoo v1.0 Перетворення за допомогою мови shell -і
шестнадцатиричные у восьмеричні Автор: Russ Sage
bc < ibase = 16
obase = 8
$HEX
!
Тонкості bc
Один з важливих моментів - це порядок, у якому ми змінювали
підстави. Спочатку - більша підстава, потім менше. Після того як
ми змінюємо ibase на 16, всі вхідні числа розглядаються як
шестнадцатиричные. Так що рядок 6 не має нового подання: ми
установлюємо obase рівним 8, а число 8 має одне й теж значення в
шестнадцатиричной і десяткової системах.
Що б відбулося, якби ми дорівняли obase до 10 ? Число 10 було
би інтерпретовано в шестнадцатиричном змісті, а шестнадцатиричное
10 - це 16. Нам би довелося записати obase у шестнадцатиричной
системі (підстава 16, оскільки 10х вхідне = 16d вихідне). Вам
прийде відслідковувати подібні речі.
Назва: otod
otod Восьмеричні в десяткові
Призначення: Переводить вхідні восьмеричні числа у вихідні
десяткові.
Синтаксис: OCT="octal_number"; DEC = '.otod'
Приклад виклику
$OCT="777" ;
$DEC='.ot
$echo $DECod'
Привласнити OCT восьмеричне число, перетворити його в десяткове,
надрукувати результат.
Вихідний текст для otod
1 :
2 # @(#) otod v1.0 Перетворення мови shell--восьмеричні в
десяткові Автор: Russ Sage
- 9
bc < ibase = 8
$OCT
!
Назва: otoh
otoh Восьмеричні в шестнадцатиричные
Призначення: Переводить вхідні восьмеричні числа у вихідні
шестнадцатиричные.
Синтаксис: OCT="octal_number"; HEX = '.otoh'
Приклад виклику
$OCT="777" ;
$DEC='.otoh'
$echo $HEX
Привласнити OCT восьмеричне число, перетворити значення OCT в
шестнадцатиричное, запускаючи otoh. Привласнити результат перетворення
HEX, відобразити значення HEX.
Вихідний текст для otoh
1 :
2 # @(#) otoh v1.0 Перетворення за допомогою мови shell -і
восьмеричні в шестнадцатиричные
Автор: Russ Sage
bc < obase = 16
ibase = 8
$OCT
!
Хитрості мови shell
Кожна мова програмування має свої власні
синтаксичні "підводні камені". Потрібні роки, щоб розібратися в
всіх тонкостях і, здається, що вивчити їх все просто неможливо.
Shell у цьому плані нічим не відрізняється від інших мов.
У цьому розділі ми розглянемо деякі моменти, про які Вам
потрібно знати, якщо серйозно програмувати мовою shell. Це дуже
вузькі області, але вони можуть стати серйозною перешкодою, якщо Ви
зштовхнетеся з ними при написанні програм.
Читайте уведення із клавіатури, поки перебуваєте в циклі,
приєднаному до програмному каналу
Команда читання мови shell читає дані зі стандартного уведення.
У ранніх версіях мови shell (змінено недавно тільки в System V), Ви
не мали можливості перенаправляти уведення для команди читання.
Питання в тім, як читати із клавіатури, поки стандартне уведення
приєднаний до кінця програмного каналу? Рішення питання - це брати
уведення безпосередньо із клавіатури. UNIX забезпечує це через
пристрій /dev/tty. Розглянемо наступний приклад:
- 10 who | awk '{ print $1 }' | while read NAME
do
echo "mail to $NAME: \c"
KB = 'Line < /dev/tty'
if [ "$KB" = "y"]
then mail $NAME
fi
done
Ця програма відображає на екрані список що зареєструвалися
користувачів і запитує Вас, чи не хочете Ви послати повідомлення по
пошті кому-небудь із користувачів. Якщо Ви відповідаєте "Y", команда
пошти запускається, причому їй на вхід передається ім'я користувача,
якого Ви вибрали.
Висновок програми awk переспрямований на стандартне уведення циклу
while. Команда читання читає з stdin, що є списком імен
користувачів, отриманим з вихідного потоку команди who. Вам
видається підказка відправити повідомлення до конкретної людини, потім
Ви переходите до команди read. Ми збираємося використовувати команду Line
(1). Вона читає по одному рядку з даного пристрою. Ми викликаємо
команду line і перенаправляємо її стандартне уведення на спеціальне
пристрій /dev/tty. Тепер уведення йде із клавіатури в той час як
цикл усе ще читає свій stdin із програмного каналу.
Змінна KB одержує значення, що рівняється з "y". Якщо
змінна має значення "y", те викликається команда mail, що в
якості параметра одержує ім'я користувача, записана в даний
момент у змінної NAME.
Запуск дочірньої мови shell
Shell - дуже багатобічна програма. Вона може працювати в
інтерактивному, фоновому й командному режимах. Її уведення може бути
переспрямовано, підключений до програмного каналу, він може бути з
убудованого тексту або з вихідного потоку приєднаної команди.
Ми хочемо звернути Вашу увагу на гнучкість мови shell на уровнях його виконання. Shell може породжувати інші мови shell для виполнения частин його роботи. До якої глибини він може опуститися? Зчи міняють працюючі дочірні мови shell виконання й результат доманд, запущених з мов shell першого рівня? На це важко ответить. Усе, що ми можемо - це випробувати деякі речі й подивитися
чи представляє інтерес те, що ми вивчили чи ні. Shell може підлогичать своє уведення зі стандартного уведення, що є або уведенням з
клавіатури, або з файлу, або із програмного каналу. Цю гнучкість
мови shell ми можемо використовувати в нашу користь. Синтаксис виглядає
наступної бразом:
echo $@ | sh
Ми відображаємо аргументи в командному рядку й посилаємо її в
програмний канал. Shell наприкінці програмного каналу читає текст
командного рядка з stdin (певного -) і виконує команди. Цей
метод також ілюструється в главі 9 у команді umntsys.
Якщо ми можемо перенаправляти стандартне уведення команди, ми можемо
також використовувати можливість уведення мови shell "документ тут".
Використовуючи позначення <<, ми можемо обмежити область тексту й направити його в стандартний канал уведення командного файлу.
Щоб продемонструвати цикл аналогічний попередній, використовуючи
тільки убудований текст, розглянемо наступний приклад:
sh << !
$@
!
- 11
Ця програма викликає shell і змушує стандартне уведення для
мови shell іти з тексту, обмеженого символами !. Ми передаємо
усе з командного рядка, так що це буде аналогічно тому, як якщо
би ми друкували команди для мови shell першого рівня.
Рівні мови shell і уведення-висновок
Іншою цікавою й загадковою областю є уведення й висновок з
мов shell, що працюють на різних рівнях. Один із прикладів пов'язаний з
спробою захопити процес номер id, коли ви поміщаєте завдання id в
фоновий режим, використовуючи символ & з командного рядка. Якщо Ви
використовуєте цю форму, Ви одержите такий результат:
$ ls &
1034
$ file1
file2
file3
де file1, file2 і file3 - висновок команди ls. Усе, що ми хочемо
зробити - це помістити процес номер id (у цьому випадку 1034) в
змінну, доступ до якої ми одержимо пізніше. Один цікавий момент
тут - якщо Ви робите ту ж саму команду усередині командного файлу,
номер процесу id не друкується.
Для того, щоб насправді захопити процес із номером id,
потрібно виявити спритність. Необхідно небагато поэкспериментировать,
щоб знайти робочу комбінацію:
$(ls &) 2 > idfile
Команда ls запускається як дочірній shell, використовуючи позначення
(). Дочірній shell міститься у фоновий режим, використовуючи символ & .
Коли результат процесу id відображений, він направляється у файл помилок
дочірньої мови shell, що його виконує. Ми просто перенаправляїм стандартну помилку у файл і одержуємо число! Тепер ми можемо сделать що-небудь типу:
$ kill -9 'cat idfile'
де процес id, переданий kill, генерується з команди cat, що
друкує процес id, захоплений раніше. Це може дати програмам
опцію "kill self", де вони можуть відслідковувати їх id, щоб вам не
довелося це робити. Програма watch, що ми бачили в главі 6
робить щось подібне.
Убудоване уведення
Редактор vi зручний доти, поки Вам не потрібно робити
порядкове редагування тексту або редагування в командному
режимі. Sed теж непоганий редактор, але в ньому не передбачена
можливість переміщення по файлі. Sed може переміщатися тільки
уперед по файлі до кінця файлу. Всі наші проблеми може вирішити
скромний редактор ed.
З редактором ed
Еd є інтерактивним редактором і в ньому є всі
необхідне для обробки виражень. Оскільки він читає стандартний
уведення для своїх команд, ми можемо поміщати в stdin убудований текст для
- 12 керування властиво редактором. Еd читає команди, як якби вони
були дані із клавіатури. Він не знає, що запущено в командному режимі.
Це відкриває зовсім новий спосіб використання моці
інтерактивного редагування в командному режимі.
Як приклад розглянемо наступну програму. Помнете, що
всі спеціальні символи в мові shell повинні бути укладені в кавычки, наприклад $. Якщо вони не укладені в лапки, то уведення буде некорректным.
ed file << -!
1, \$s/^ *//
w
q
!
У цьому прикладі редагується файл за назвою "file" і над ним
виконується кілька команд. Перша команда говорить "Від першої
рядка до останньої, для кожного рядка, що має порожні символи в
початку рядка, за яких треба будь-яка кількість таких же
символів, замінити ці символи "нічим". Запишіть файл і вийдіть." Ця
процедура видаляє пробіли з початку рядка.
З файлом a.out
Можливість убудованого тексту також можна використовувати, щоб
автоматизувати запуск програм. Вам потрібно записати вхідні дані,
необхідні, щоб програма виконувала бажане завдання, і помістити
їх у текст програми. (Це щось начебто побудови макросів клавіатури
для прикладних програм для PC).
У наступному прикладі виконується файл, щоМ, a.out запускається як
дочірній shell. Його уведення береться із самого файлу, а висновок передається
команді more, так що ми можемо зробити посторінковий висновок.
$ (a.out < > text
> input
> lines
> !
) | more
Це можна надрукувати безпосередньо із клавіатури. Ми використовуємо
символи дужок, оскільки, якщо безпосередньо друкувати цей код,
shell буде видавати підказку PS2 аж до знака !, потім виконає
команду. Єдине, що ми можемо зробити, щоб він не вийшов
автоматично - це продовжувати запитувати уведення, опускаючи його на
рівень нижче.
C архівами мови shell
Архіви мови shell - це один з найпростіших способів упаковать текст у самоустановлювальну програму. Ідея полягає в тому, що
ми використовуємо командний файл мови shell, щоб упакувати деякий
текст. Цей текст може бути документом, командним файлом або навіть
вихідним текстом програми.
Ми використовуємо конструкцію убудованого тексту, щоб передати
текст в shell, що потім пересилає його у визначені файли.
Нижче наведений приклад архіву, що може бути у файлі.
$ cat archive
- 13
#
# Це архівний файл текстових файлів 1, 2 і 3
#
echo "витягаємо текстовий файл 1"
cat > text1.sh << !
#
# Це приклад текстового файлу 1
#
who | sort
!
echo "витягаємо текстовий файл 2"
cat > text2 << !
Цей уміст другого файлу. Це не програма, а просто текст.
Помітьте, що йому не потрібно рядків коментарю, тому що
запущений shell знає, що це уведення. Але не намагайтеся запускати
text2, тому що у Вас однаково нічого не вийде.
!
echo "витягаємо текстовий файл 1"
cat > text3.c << !
/* Цей уміст файлу 3, Си програма */
main()
{
printf("hello world");
}
!
#
# кінець архівного файлу
#
При виконанні архів проходить через три команди cat. Перша доманда cat створює файл text1.sh (командний файл мови shell), text2
(звичайний текст) і text3.c (Сі-програма). Все це виконується після
того, як Ви наберете на клавіатурі "archive". Це зручно, якщо потрібно
перенести текст в інше місце. Замість того щоб пересилати три фаїла, нам потрібно переслати один. Замість трьох файлів, з'єднаних разом,
у нас три окремо упакованнных файли, кожний з яких восстанавливает себе при запуску архіву. Таким чином, нам не прийде ворожити,
намагаючись представити який текст у який файл потрапить.
Керування статусом циклу
Іноді умовні вираження циклу потрібно підбирати спеціальним
образом, щоб вони відповідали нашим потребам. Це відбувається не
часто, однак бувають ситуації, коли Ви можете захотіти використовувати
певний синтаксис. У таблиці 10-1 наведені три різних способи
зробити умова циклу while "щирим". Помнете, що shell шукає
успішний статус виходу - статус (0) з останньої синхронно
виконуваної команди.
Таблиця 10-1
Способи змусити цикл бути "щирим"
+-і-і-і-і-і-і-і+-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і+
| Цикл | Умова зі значенням "істина" |
- 14 +-і-і-і-і-і-і-і+-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і+
|while true |True - це команда в /bin, що віз-|
| |вращает статус 0 |
|while[1 -eq 1]|мы використовуємо тут тестову команду, |
| |чтобы повернути статус 0 |
|while : |мы використовуємо убудовану пропозицію |
| |shell'а, щоб повернути статус 0 |
+-і-і-і-і-і-і-і+-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і-і+
Фільтри й синтаксис
Раніше в цій книзі вже йшла мова про фільтри. Не всі команди
є фільтрами або можуть бути використані як фільтри.
Згадаєте визначення фільтра - це команда, що бере уведення з
аргументів командного рядка, якщо вони є. Інакше уведення читається з
стандартного уведення.
Чому всі команди не можуть діяти як фільтри? Тому, що
вони не призначені для цього. Візьмемо, наприклад, ls. Що робить ls?
Вона видає список файлів у поточному каталозі. Якщо ми говоримо "ls
file", він видає інформацію тільки для цього файлу. Якщо ми говоримо
"echo file | ls", ls не подає інформацію про файл, але видає список
файлів у поточному каталозі, тому що ls не дивиться в стандартний
уведення, якщо в командному рядку немає аргументів.
Один важливий момент, пов'язаний з фільтрами - це спосіб їхнього виклику.
Якщо Ви поміщаєте ім'я файлу в командний рядок, фільтр відкриває файл
і читає дані. Помнете, що фільтри хочуть читати дані. Якщо Ви
приєднуєте стандартне уведення до фільтра, воно думає, що те, що він
читає із програмного каналу- це дані. Якщо Ви дасте фільтру
імена файлів, Ви не одержите того результату, що очікуєте.
Давайте розглянемо кілька прикладів. Команда UNIX wc - це фільтр.
Ми можемо викликати її як "wc file1 file2 file3", щоб вона підрахувала
слова в трьох файлах. Що було б, якби ми сказали: "ls file1 file2
file3 | wc" ? Wc підрахувала б суму символів, які видала б ls.
У цьому випадку в рядку file1, file2, і file3 - 15 символів. Як нам
одержати реальні файлові дані, а не імена файлів в wc? Змінюючи
спосіб, яким ми викликаємо wc:
cat file1 file2 file3 | wс
Шляхом попереднього з'єднання файлів, дані передаються на
вхід wc, і wc підсумує підраховані суми символів, умісту
файлів. Та ж сама концепція застосовна для всіх команд фільтрів. Ще
одною подібною командою є awk. Ми можемо сказати "awk file", і
команда прочитає вміст файлу, або "cat file | awk", і одержимо
такий же результат. Ми не можемо використовувати синтаксис "ls file | awk",
т.к. awk виконує свою програму тільки над символами в ім'ї
"file".
Недоліки/особливості програмування мовою shell
У цьому розділі ми розглянемо деякі недоліки мови shell. До
кінця поки не ясно, чому проявляються ці дефекти або особливості.
Так уже shell працює й такий вуж він насправді.
Програма для перенапрямку помилки
1 :
2 # @(#) перенапрямок помилкового значення змінної в цикл,
приєднаний до програмного каналу
3
4 N=1
5 echo "початкове значення N = $N"
6
7 echo "1\n2\n3" | while read LINE
8 do
9 N=2
10 echo "значення в циклі N = $N"
11 done
12
13 echo "кінцеве значення N = $N"
Програма показує, що різні присвоєння, зроблені в дочерних мовах shell, не поширюються на їхніх батьків. Рядок 4
привласнює N початкове значени 1. Потім значення N відображається в
рядку 5 для перевірки. Вся хитрість цієї програми укладена в рядку
5. Ми відправляємо символи "1 новий рядок 2 новий рядок 3" у программный канал і даємо це на вхід циклу while. Таким чином, ми
змушуємо цикл виконати три ітерації. Приєднуючи висновок до програмному каналу, ми створюємо дочірній shell, щоб виконати цикл while.
Усередині циклу while ми змінюємо значення N і друкуємо його для проверки.
Наприкінці циклу ми друкуємо остаточне значення N. Воно більше
не дорівнює 2 як це було усередині циклу, а дорівнює 1, як це було після
першого присвоєння. Нижче представлений приклад прогону цієї програми.
$ redir
начально значення N = 1
значення в циклі N = 2
значення в циклі N = 2
значення в циклі N = 2
кінцеве значени N = 1
Це показує, що значення змінної передається долілиць дочірньому
мові shell, але зміни в дочірньому shell не передаються родительскому.
Некоректний код повернення
Звідки shell знає, чи є коректними ті або інші коди
повернення? На це складно відповісти. Іноді виявляється, що код
помилковий, коли помилку містить ваша програма.
Наприклад:
1 :
2 # @(#) помилка коду повернення
3
4 echo "Уведіть команду : \з"
5 read CMD
6
7 eval $CMD
8 echo "\$? = $?"
9
10 if [ $? -eq 0 ]
11 then echo гарний вихід - $?
12 else echo поганий вихід - $?
13 fi
Програма починається з того, що в рядку 4 Вам видається
підказка для введення команди. Команда читається, рядок 7 оцінює
не потрібні чи їй додаткові змінні й виконує її. Помнете,
що нам потрібно оцінити параметр у тому випадку, якщо хто-небудь сказав
щось типу "echo $HOME". Якщо команди eval ні, то друкується
- 16 літеральний рядок $HOME. Після команди eval друкується
дійсне значення $HOME. Так що нам доводиться використовувати
команду eval у цій ситуації. Після того як команла виконаний рядок
друкує статус виходу, посилаючись на $?. Це зовсім нормально.
Рядок 10 потім використовує тестову команду, щоб програма
розгалузилася залежно від коду повернення. Це і є те місце, де
помилка. Величина, що бачить тестова команда не збігається з тієї,
яку друкує луна.
$ status
уведіть команду: ls -z
ls : illegal option -іz
usage : -1ACFRabcdfglmnopqrstux [files]
$? = 2
гарний вихід - 0
Це показує, що ls запустили в помилковому режимі. Ls
надрукував своє повідомлення про помилку й повернув код повернення рівний 2.
Однак тестова команда бачить $? як значення 0 і вибирає галузь
істина. Чи можете ви знайти помилку в рядку 8 програми ? Це гарна
нота для закінчення роздягнула про помилки.
Хитрості редактора Vi
Одна із самих чудових особливостей UNIX - це можливість
вийти із програм так, щоб Ви могли запускати інші команди поза
мови shell. Це було розроблено усередині UNIX і є простим і
потужним засобом. Використання деяких прийомів, описаних нижче может зробити розробку програми більше простій і швидкої.
Повернення в shell
Повернення в shell - дуже корисна можливість у редакторі vi.
Ви можете записати Вашу програму в редакторі, вийти з нього,
запустити програму, повернутися назад у редактор і т.д. Цей цикл
редагування - трансляція - перевірка може бути виконаний з
редактори. Із цими можливостями входу й виходу з редактора Ви
можете закінчити сеанс роботи без реального знищення редактора.
Редактор vi також є редактором ex. Vi - це візуальна
частина ex. Отже, Ви можете вийти в shell двома шляхами.
Перший - використовуючи змінну sh, що встановлена в
редакторі ex. Ви можете набрати
: sh
поки ви в vi або просто "sh", якщо Ви в ex. Редактор прямо залишає
shell, що Ви визначили в змінної sh. Звідки редактор знає
який shell Ви запускаєте? Це можна визначити по реєстраційної
змінної оточення мови shell. Якщо Ваш shell - /bin/sh, а Ви хотиті запустити /bin/shV, Ви можете переустановити значення змінної,
надрукувавши ":set sh=/bin/shV"
Інший спосіб виходу з vi - це з використанням синтаксису:
:!sh
де "sh" дає Вам shell (/bin/sh). Зверніть увагу, що відбувається.
Ви запускаєте shell (запуска_ по :!), якому дана команда
запустити shell (:!sh). Коли Ви, нарешті, запукаете цей shell,
виходить, що у Вас запущений зайвий shell. Це дуже наочно
представлено в лістингу ps, наведеному нижче
- 17
UID PID PPID C STIME TTY TIME COMMAND
russ 35 1 0 Jul 5 co 0:50 -shv
russ 1233 35 0 04:30:15 co 0:57 vi file
russ 1237 1233 0 04:43:13 co 0:01 sh -c sh
russ 1238 1237 0 04:43:15 co 0:02 sh
У третьому рядку все сказано. З vi ви запустили shell з опцією
-із для запуску мови shell . Це марна витрата цілого shell! А
якщо використовувати зазначений вище синтаксис або просто ":sh", то така
ситуація не виникне.
Підтримка Escape
Крім того, що редактор vi можна покинути по Esc, він
підтримує деякі інші можливості для виходу. Володіючи
різними можливостями виходу, інструментальні засоби можуть
виконувати для Вас більшу частину роботи. Перший варіант синтаксису ":!cmd", що є префіксом для запуску будь-якої команди поза
редактори. У цьому випадку команда може бути будь-якою командою роздягнула
(1).
Другий варіант синтаксису - це ":!!". Це означає вийти (:!) і
використовувати останній командний рядок як аргумент для запуску в
новій мові shell. Наприклад, якщо ми сказали: ":!ls", потім ":!!",
:ls буде запущена знову. Другий ! посилається до всій попередній домандной рядку.
Третій варіант синтаксису - це ":! %". Це означає вийти (:!) і
запустити команду, ім'я якої є ім'ям цього файлу (%). Коли
ви натискаєте повернення каретки, % - заміщається ім'ям файлу, що дуже
зручно при редагуванні командних файлів. Ви можете зробити
що-небудь типу:
$ vi tool
. . . edit . . .
:w
Ви викликаєте vi з ім'ям файлу, так що vi запам'ятовує ім'я
"tool" у своєму буфері. Ви можете змінити щось прямо отут в
редакторі, записати зміни на диск, потім запустити нову копію
файлу. Редактор заповнює файл із ім'ям "tool" і запускає його. Коли
Ви виходите з файлу, що виконується, "tool", Ви попадаєте назад в
редактор, готові внести зміни в текст і запустити програму
знову.
Одна з гарних послідовностей - це відредагувати файл,
зробити зміни, записати їх, запустити файл, використовуючи %, внести
зміни ще раз, запустити знову програму, надрукувавши :!!, що
перезапускає останню команду escape, :! % . У такий спосіб цикл
виходів і запусків програми утворить три натискання клавіатури, :!!.
Ми навіть можемо використовувати цю можливість для компіляції
програм на С. Якщо в нас є командний файл, що називається
"cg" (генератор компіляції) ми можемо простіше використовувати vi:
F = 'echo $ 1 | sed -e "s/^\(.*\).c$/\1"'
cc $1 -o $F
Потім ми можемо виконати послідовність такого типу:
$ vi test.c
...edit...
:!cg %
або те ж саме коротше
- 18
: !cg test.c
і закінчується створенням модуля, що виконується, "test".
Макроси
Інша можливість vi, що підтримує простий вихід, - це
механізм макросів. Хоча головним чином макроси потрібні для того, щоб
можна було поміщати команди редагування в іменовані регістри,
які часто використовуються. У такий спосіб замість того, щоб
використовувати синтаксис знову й знову, Ви просто використовуєте макрос.
Нижче наведений приклад макропідстановки:
i
s/^[^ ]*/ [^ ]*/
"add
@a
Спочатку потрібно перейти в режим вставки, щоб ми могли помістити
команду в наш файл редактора. Ми друкуємо команду підстановки й
натискаємо ESC, щоб закінчити роботу в режимі вставки. Команда
підстановки говорить "У рядках, які починаються з непустого
символу, за яким ідуть один або кілька символів такого ж
типу, поставити пробіл перед непустою послідовністю символів".
Далі ми друкуємо "add", де "а" позначає іменований регістр a і
dd позначає перемістити рядок у буфер. Тепер рядок підстановки
перебуває в буфері а. Щоб неї виконати ми просто надрукуємо @a в
командному режимі vi.
Щоб вийти ми можемо виконати ту ж послідовність
дій, але помістити команду типу
:!ps -ef
у редактор і переписати її в буфер. Потім, коли ми говоримо @a, ми
входимо в shell і запускаємо команду ps. Команди такого типу можна
поміщати в іменовані буферы від a-z.
Останній спосіб використання макросів для підтримки виходу - це
через команду map. Ця команда є в ex і адресується попередньої
двокрапкою : з vi. Синтаксис для команди map виглядає так:
:map lhs rhs
Це встановлює відображення лівої сторони на праву сторону.
Приклад присвоєння виглядає так:
:map w :!who^M
Тепер щораз, коли Ви друкуєте w, буде виконуватися
дія виходу через ex, друкуватися команда who, потім друкуватися
повернення каретки, що відправляє всю цю послідовність на
виконання. Все це по одному натисканню клавіатури.
Саме смішне починається, коли Ваш термінал має
функціональні клавіші. Vi звертається до функціональних клавіш по #0
-#9. Тепер ми можемо зарезервувати функціональні клавіші для
команд виходу. Просте присвоєння буде:
:map #1 :!ps -ef^
Щораз, коли Ви натискаєте функціональну клавішу F1,
- 19 запускається команда ps -ef.
Команда "One-Liners" - малюсінька, але потужна
Наступний список - це добірка звичайних команд, використаних
таким чином, щоб одержати потужний ефект. Як майстер військового
мистецтва, що вбиває голими руками, майстер UNIX часто може
скласти разом кілька звичайних команд і досягти колосального
ефекту. Деякі рядки, які будуть представлені нижче, можна
зустріти в інших місцях цієї книги, але вони приводяться тут
повторно для полегшення пошуку.
Рядки групуються відповідно до команди, що є
ключовий у даному рядку, однак, іноді складно виділити таку
команду як, наприклад, у випадку програмного каналу, коли Ви із двох
сторін маєте важливі команди. Помітьте, що деякі із цих команд
є стандартними командами UNIX, у той час як інші - це
командні файли й програми, представлені раніше в цій книзі.
ACCTCOM
* прочитати всю Вашу облікову інформацію, починаючи з останньої команди.
acctcom -b -u$LOGNAME
* показати всі облікові записи, запущені з Вашого термінала й того,
який запущений як суперкористувач
acctcom -u# -l'tty'
BANNER
* надрукувати повідомлення на трьох рядках
banner "line 1" "line2" "line3"
* надрукувати день тижня й дату на одному рядку, час на інший
banner "'date|cut -d' ' -f1,3'" "'date|cut -d''-f4'"
* послати повідомлення на екран іншого користувача
banner "Привіт" "там" > /dev/tty01
BASENAME
* очистити шлях
echo "Я за пристроєм 'basename\'tty\' ' ''
BC
* передати формулу на вхід команді bc, що повинна виконати
множення й привласнить результат PROD
PROD = 'echo $NUM1 * $NUM2 | bc'
CAT
- 20
* передати символи із клавіатури у файл
cat > file (друкувати поки не зустрінеться символ ^D
для припинення читання)
* одержати уведення з конструкції "документ тут"
cat << -!
Це зразок тексту, що друкується на екрані !
CC
* множинна компіляція у фоновому режимі з однієї командної
рядка
cc file1.c & cc file2 & cc file3.c &
CD
* перейти в каталаг, у якому перебуває файл
cd 'ім'я директорія\'шлях файл\''
* перейти в каталог, що записаний у змінної
DESTINATION="/usr/bin"
cd $DESTINATION
* перейти в каталог, записаний у файлі
cd 'cat dest_file'
CHMOD
* включити біт виконання файлу
chmod +x file
* включити біт зміни ідентифікатора користувача й дозволити
усім виконання файлу
chmod 4755 file
* установити біт sticky у включений стан
chmod 1755 file
CHOWN
* установити себе власником файлу
chown $LOGMAME files
* тим же саме іншим способом
chown 'who am i| cut -d' '-f1' files
* змінити право власності для дерева
- 21
cd dest
find . -print | sort | while read FILE
do
chown russ $FILE
done
CP
* скопіювати три рівні файлів в один вкаталог /tmp
cp */*/* /tmp
* тим же саме іншим способом
cp 'find . -type f -print' /tmp
* перемкнути користувальницька пропозиція
cp -z
CPIO
* перемістити дерево системи файлів у нове місце розташування
cd $SRC
find .-print | sort | cpio -pdv $DEST
* скопіювати дерево системи файлів на гнучкий диск
cd $HOME
find .-print | sort | cpio -ocBv > /dev/rfd0
* відновити копію на стримере
cd $DEST
cpio -icBvt < /dev/rfd0
* виконати "ls -l" на копії стримера
cpio -icBvt < /dev/rfd0
CRON
* запустите Ваш генератор повідомлень про статус щочетверга
в 6:00 a.m.
0 6 * * 4 /usr/russ/bin/status_msg
* chmod на файл паролів
* * * * * /bin/su root -c "chmod 777 /etc/passwd"
CU
* безпосередньо звернутися послідовному порту на швидкості
1200 бод
cu -ltty00 dir
* безпосередньо звернутися до послідовного порту на швидкості
9600 бод
cu -ltty00 -s9600 dir
* автоматично викликати іншу систему, використовуючи комбінацію
dial/modem
cu -acua0 555-1212
- 22
CUT
* відітнути перше поле з файлу passwd
cut -d: -f1 /etc/passwd
* відітнути ім'я з лістингу команди who
who | cut -d' ' -f1
who | awk '{print $1}
DD
* повна гнучка копія доріжка за доріжкою
dd if = /dev/fd0 of=/dev/fd1
DOS
* скопіювати всі файли даного каталогу на дискету DOS
doscp * a:
* скопіювати всі файли з дискети DOS у даний каталог
dosls a: > /tmp/dosf
for FILE in 'cat /tmp/dosf'
do
doscp a:$FILE
done
DU
* видати загальна кількість блоків для всіх каталогів в /
du -s /*
* надрукувати кількість використаного місця в каталозі
кожного користувача
echo "total bytes: 'expr\'du -s $1\' \* 512'"
ECHO
* надрукувати значення змінної shell'а
echo $PATH $CDPATH
* надрукувати висновок упереміш зі звичайним текстом
echo " Моє ім'я $LOGNAME або
'logname' або 'who am i|cut -d' ' -f1'"
* надрукувати символи упраления в лапках і без
echo "\n\t Це записано в лапках"
echo \\n\\t Це записано без лапок
* надрукувати й залишити курсор наприкінці того ж рядка
- 23
echo -n "prompt: "
echo "prompt: \c"
ED
* запустити ed автоматичски з конструкцією
"документ тут"
ed /etc/passwd <<-!
1,$p
g/root/s//noroot
w
q
!
EXPR
* помножити два числа
expr 512 \* 1024
* збільшити змінну на визначене значення
x = 0; INC = 5
X='expr $X + $INC'
FILE
* знайти всі текстові файли
file * | fgrep text
* надрукувати імена тільки текстових файлів
file * | fgrep text | cut -d: -f1
* more всі текстові файли
more 'file * | fgrep text | cut -d: -f1'
FIND
* знайти всі файли в системі
find / -print | sort
* знайти всі файли й роздрукувати список у форматі long
find / -exec ls -ld {} \;
* надрукувати імена всіх регулярних файлів
find / -type f print
* знайдіть всі каталоги й роздрукуйте вміст
find / -type d print | while read DIR
do
echo "listing $DIR"
ls $DIR
done
* знайдіть всі файли, які були модифіковані в останні
24 години й роздрукуйте їхній список у форматі long
find / -atime -0 -exec ls -ld {} \;
- 24
* знайдіть всі файли setuid і setgid
find / -perm -4000 -o -perm -2000 -exec ls -ld {} \;
FINGER
* укажіть всіх користувачів, що вийшли із системи
finger 'who | cut -d' ' -f1'
* укажіть всіх користувачів у файлі passwd
cut -d: -f1 /etc/passwd | while read NAME
do
finger $NAME
done
GREP
* знайти випадки вживання шестнадцатиричных чисел у файлі
даних
od -x datafile | grep 'A3F09'
* знайти своє ім'я в системі
find / -type f print | while read FILE
do
grep "russ" $FILE /dev/null
done
HEAD
* озаглавте всі текстові файли в поточному каталозі
file * | fgrep text | cut -d: -f1 | while read FILE
do
echo "-і-і-і-і"
echo "$FILE"
echo "-і-і-і-і"
head "$FILE"
ID
* визначити, хто в цей момент є суперкористувачем
if [ "'id'" = "uid=0(root) gid=0(root)" ]
then echo "you are root"
fi
* тим же саме іншим способом
if id | fgrep root > /dev/null
then echo "you are root"
fi
KILL
* знищте себе (вивантажите)
kill -9 0
kill -9 $$
* завершите роботу системи
kill -1 1
* знищте останній процес, запущений у фоновому режимі
kill -9 $!
- 25
* знищте процес, ідентифікатор якого перебуває у файлі
kill -9 'cat idfile'
LINE
* взяти рядок з термінала
LINE='line < /dev/tty'
* взяти рядок зі стандартного уведення
cat datafile | while LINE = 'line'
do
echo $LINE
done
LOGIN
* перейти зі сгенерированной підказки login ???
login: ^d
login:
* одержати деяку внутрішню інформацію
(програма strings - це BSD)
strings /bin/login | more
LOGNAME
* надрукувати інформацію про свій пароль
grep '^'logname ':' /etc/passwd
* одержати інформацію про свій процес
ps -fu 'logname'
LS
* видати список схованих файлів
ls -ad .*
* видати розмір файлу в байтах
ls -l file
* видати розмір файлу в блоках
ls -s file
* видати інформацію про права доступу по записі всіх
зарегестрировавшихся в системі
ls -li 'who |sed "s/^[^ ]* *\([^ ]*\) .*$/\/dev\/\1/p"'
* одержати допомогу по испоьзованию команди
ls -z
* видати список тільки каталогів
ls -al |grep "^d"
MAIL
* послати пошту всім користувачам
- 26
cut -d: -f1 |while read USER
do
echo "mailing to $USER"
mail $USER
done
* послати пошту з файлу
mail russ < /etc/passwd
* послати пошту із програмного каналу
echo "Це текст пошти" | mail russ
MORE
* надрукувати всі файли поточного каталогу
more *
* надрукувати 10 рядків за раз
more -10 file
cat file | more -10
MKDIR
* опуститися на максимальну глибину
while :
do
mkdir x
cd x
done
* тим же саме іншим способом
PATH="x"
while :
do
mkdir $PATH
PATH="$PATH/x"
done
NCHECK
* знайти всі файли, приєднані до vi
ls -li /bin/vi
40 -rwwx--x--t 1109344 Feb 14 1985 /bin/vi
ncheck -i 40 /dev/root
* знайти всі файли установки ідентифікатора користувача
ncheck -s
NM
* подивитися символьні таблиці всіх nonstripped
файлів, що виконуються
nm 'file *| grep "not stripped"|sed "s/^\(.*\):.*$/\1/"
OD
* подивитися символи в іменах файлів у поточному каталозі
- 27
od -c .
* надрукувати значення функціональних клавіш, комбінацій
клавіш, і.т.буд.
od -cb (натисніть комбінацію клавіш)
^d (друкує рядок)
(натисніть що-небудь ще)
^d (друкує наступний рядок)
^d (выыходит з od)
* зробити дамп копії на стримере
od -c /dev/rfd0
* зробити дамп файлової системи
od -c /dev/root
PASSWD
* як суперкористувач Ви можете встановити як пароль
будь-який рядок
# passwd russ
Changing password for russ
(Зміна пароля для russ)
Enter new password (minimum of 5 characters)
(Уведіть новий пароль (мінімум 5 символів))
Please use combination of upper, lowercase letters
and numbers
(Прохання використовувати комбінації чисел і букв в
верхньому й нижньому регістрах)
New password: junk
(Новий пароль: junk)
Re-enter new password: junk
(Новий пароль: junk)
#
* як звичайний користувач Ви повинні будете вводити пароль із обліком
кількісних обмежень і обмежень по довжині
$ passwd russ
Changing password for russ
(Зміна пароля для russ)
Enter new password (minimum of 5 characters)
(Уведіть новий пароль (мінімум 5 символів))
Please use combination of upper, lowercase letters
and numbers
(Прохання використовувати комбінації чисел і букв в
верхньому й нижньому регістрах)
New password: junk
(Новий пароль: junk)
Too short. Password unchanged.
(Занадто короткий. Пароль не змінений)
$
PR
* вивести многоколоночный список імен файлів
ls $@ | pr -5t
* надрукувати файли зі списку
- 28
pr 'find . -name "*.c" -print | sort'
PS
* надрукувати повну інформацію про всі активні процеси
ps -aef
* надрукувати інформацію про всі процеси, керованих
Вашим терміналом
ps -f
* надрукувати інформацію про процеси, пов'язаних з терміналом tty00
ps -ft00
* надрукувати інформацію про процеси, пов'язаних з користувачем russ
ps -furuss
* BSD синтаксис для печатки всіх процесів
ps -aux
* BSD синтаксис для печатки всіх процесів, пов'язаних з
термінальним пристроєм
ps -xut00
PWD
* зберегти поточний робочий каталог
PWD='pwd'
* повернутися в раніше збережений робочий каталог
cd $PWD
RM
* видалити всі файли, крім каталогів з файлами
rm *
* видалити порожні каталоги
rmdir dirs
* видалити каталоги, що мають файли
rm -r dirs
* видалити всі файли в режимі, коли система не буде
задавати ніяких питань
rm -rf *
* видалити кожний файл у системі окремо
rm -rf /
SH
* прочитати список поэлементно
for ELEMENT in 'cat /etc/motd'
do
- 29
echo $ELEMENT
done
* прочитати список построчно
cat /etc/motd | while read LINE
do
echo $LINE
done
* цикл поки - назавжди (while-forever)
while :
do
echo $PS1
read CMD
case $CMD in
"") break;;
esac
done
* керований цикл while
read CMD
while [ "$CMD" != ""]
do
case $CMD in
user-cmd) do_it;;
esac
echo $PS1
read CMD
done
* переполнениие тестового стека при обробці
переривання
trap "echo trapping; kill $$" 2 3 15
* вивантаження з мови shell декількома способами
exit
eof character (usually control -d)
kill -9 0
kill -9 $$
STTY
* подивитеся всі свої установки
stty -a
* подивитеся термінальні установки
іншого термінала
stty -a < /dev/tty01
* установити передачу бод на іншу швидкість для
іншого термінала
stty 300 < /dev/tty01
* динамічно встановити control-A як клавішу
переривання
stty intr ^a
* включити луну-супровід термінала
stty -echo
- 30 SU
* тестовий цикл для знищення легких паролів
awk '{FS =":"; print $1,$5} '/etc/passwd|while read N C
do
echo "\n$N\t$C"
su $N
done
TAIL
* простежити в реальному часі запис шипиків файлу
входу в систему (logfile) uucp
tail -f /usr/spool/uucp/LOGFILE
* подивитися останній рядок файлу
tail -1 file
* подивитися останні 10 символів змінної
echo "$VAR" | tail -10c
TAR
* зробити копії файлів у Вашім home-каталозі не розриваючи файл, але
формуючи копії на шматки по 1200 блоків
cd
tar cvefbk /dev/rfd0 10 1200 .
* виконати команду "ls-l" для копій файлів
tar tvf /dev/rfd0
* відновити копії файлів
cd $DEST
tar xvf /dev/rfd0
* скопіювати файли в tar , відсортувавши їх
tar cvfk /dev/rfd0 1200 'find . -print | sort'
TEE
* відправте свій висновок на екран іншого термінала
sh | tee /dev/tty01
* захопите висновок інших команд
fsck /dev/root | tee capture
cu -ltty00 dir | tee capture
TEST
* перевірте еквівалентність двох рядків
test "$S1" = "$S2"
* перевірте еквівалентність двох чисел
test "$N1" -eq "$N2"
* тим же саме іншим способом
(помітьте що /bin/[приєднано до /bin/test)
- 31
[ "$S1" = "$S2" ]
[ "$N1" -eq "$N2" ]
TOUCH
* зробіть поточний доступ і зміните час всіх файлів у Вашім
home каталозі
find $HOME -exec touch {} \;
find $HOME -print | while read FILE
do
touch $FILE
done
TTY
* показати права доступу по записі на Вашім терміналі
ls -l 'tty'
* включити й відключити доступ користувачів до Вашого термінала
chmod 666 'tty'
chmod 600 'tty'
UUCP
* скопіювати імена всіх файлів у файл у загальнодоступний каталог на
іншій системі
for FILE in 'cat datafile'
do
echo "копіювання $FILE"
uucp $FILE sys! ~/user
done
* поставити файл у чергу, не ініціювати виклик, взяти файл із
Вашого первісного каталогу, не копирровать його в spool
каталог.
uucp -r -c file sys!/tmp
VI
* виконаєте поточний рядок як команду мови shell
:.w !sh
* тим же саме іншим способом, використовуючи макрос
"ayy
@a
* вийти безпосередньо в shell
:sh
* скомпілювати поточний файл
:!sh
* запустити ім'я поточного файлу як комаду мови shell
:!cc %
* запустити ще раз останню команду
:!%
- 32
* запустити команду й помістити ввывод на поточну
рядок (переписати)
:.!who am i
* запустити команду й помістити ввывод на новий рядок
:.r !who am i
:r !who am i
* відредагувати файл, що перебуває десь в
системі
:e 'path termcap'
* помістити long лістинг файлу, що перебуває
десь у файлі редактора
:.!ls -l 'path init'
WC
* друкує кількість людин, зареєстрованих у системі
echo "Усього 'who | wc -l' людина ввійшла в систему"
* друкує кількість сторк у всіх вихідних файлах
find /usr/src -name "*.c" -exec cat {} \; | wc -l
WHO
* друкує кількість і імена зареєстрованих
користувачів
who | awk '{ print "user:",$1,"\tdevice:",$2
cnt = cnt + 1
} END { print cnt,"користувачі, що вийшли із системи"}'
* друкує
who | while read NAME TTY TIME
do
echo "користувач: $NAME tty: $TTY time: $TIME
done
[...]
Початок
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [72] [73] [74] [75] [76] [77] [78] [79] [80] [81] [82] [83] [84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94] [95] [96] [97] [98] [99] [100] [101] [102] [103] [104] [105] [106] [107] [108] [109] [110] [111] [112] [113] [114] [115] [116] [117] [118] [119] [120] [121] [122] [123] [124] [125] [126] [127] [128] [129] [130] [131] [132] [133] [134] [135] [136] [137] [138] [139] [140] [141] [142] [143] [144] [145] [146] [147] [148] [149] [150] [151] [152] [153] [154] [155] [156] [157] [158] [159] [160] [161] [162] [163] [164] [165] [166] [167] [168] [169] [170] [171] [172] [173] [174] [175] [176] [177] [178] [179] [180] [181] [182] [183] [184] [185] [186] [187] [188] [189] [190] [191] [192] [193] [194] [195] [196] [197] [198] [199] [200] [201] [202] [203] [204] [205] [206] [207] [208] [209] [210] [211] [212] [213] [214] [215] [216] [217] [218] [219] [220] [221] [222] [223] [224] [225] [226] [227] [228] [229] [230] [231] [232] [233] [234] [235] [236] [237] [238] [239] [240] [241] [242] [243] [244] [245] [246] [247] [248] [249] [250] [251] [252] [253] [254] [255] [256] [257] [258] [259] [260] [261] [262] [263] [264] [265] [266] [267] [268] [269] [270] [271] [272] [273] [274] [275] [276] [277] [278] [279] [280] [281] [282] [283] [284] [285] [286] [287] [288] [289] [290] [291] [292] [293] [294] [295] [296] [297] [298] [299] [300] [301] [302] [303] [304] [305] [306] [307] [308] [309] [310] [311] [312] [313] [314] [315] [316] [317] [318] [319] [320] [321] [322] [323] [324] [325] [326] [327] [328] [329] [330] [331] [332] [333] [334] [335] [336] [337] [338] [339] [340] [341] [342] [343] [344] [345] [346] [347] [348] [349] [350] [351] [352] [353] [354] [355] [356] [357] [358] [359] [360] [361] [362] [363] [364] [365] [366] [367] [368] [369] [370] [371] [372] [373] [374] [375] [376] [377] [378] [379] [380] [381] [382] [383] [384] [385] [386] [387] [388] [389] [390] [391] [392] [393] [394] [395] [396] [397] [398] [399] [400] [401] [402] [403] [404] [405] [406] [407] [408] [409] [410] [411] [412] [413] [414] [415] [416] [417] [418] [419] [420] [421] [422] [423] [424] [425] [426] [427] [428] [429] [430] [431] [432] [433] [434] [435] [436] [437] [438] [439] [440]