Користувач:Whirlwind
Матеріал з docs.linux.org.ua — збірника документації з Unix/Linux українською мовою.
< Користувач:WhirlwindБлог користувача Whirlwind
Мотивація
Згадав тут один епізод.
Захотілося мені свого часу повністю замінити піратські програми на своєму компі їх вільними аналогами. Типу, фіг з ним, з Windows, але все інше щоб було легальне. Ну, скачав ОпенОфіс (пара сотень метрів, між іншим, немало для тодішнього діалапу), встановив, почав якось з ним жити. Рік прожив, а мо й більше, коли, власне, і стався цей самий випадок.
Я на роботі розмовляв з якимось товаришем біля його машини. Відповідно, були там запущені якась кількість програм. Щоб схеми, описи протоколів та іншу фігню передивлятись. Ну, і я, чисто автоматично, беру і згортаю якийсь документ. А колега на мене дивиться та й каже: "Чого ти його згортаєш? Закрий нафіг. Це ж вордівський файл, він же за пару секунд відкриється, як треба буде". От. І в той момент, в одну секунду буквально, я й зрозумів, яким дурнем був останні півтора роки. Бо censored ОпенОфіс запускається фіг знає скільки, і одного разу запустивши, краще його вже не закривати. Але ж, блін, сила самонавіювання: я вже й звик, і думав, що воно так нормально, що так і треба, нема нічого незвичайного...
А пригадалось це не просто так, а у зв’язку з постом у LHB. Він там обс... обговорює фразу типу "Проблема в тому, що в люди не наполегливі у переході на Linux. Вони не хочуть визнати, що деякі речі там робляться інакше, ніж у Windows..." Дійсно, так воно і є. Наприклад, краще тримати текстові редактори запущеними.
Заголовки bash-скриптів
Будь-який bash-скрипт починається з магічного напису #!/bin/bash. Ті, хто уважно читав підручники, можуть навіть пригадати, що магічними насправді є лише символи #!, а все, що за ними — шлях до інтерпретатору. Але мало кому відомо, що в якості останньго зовсім не обов’язково використовувати одну з багатьох різновидностей sh. Залежно від змісту файлу можна вказати /bin/perl або /usr/bin/awk. А можна взагалі обійтися без вказування інтерпретатору.
В якості прикладу розглянемо такий простенький скриптик:
#!/bin/bash
awk '
{ print $2 }
' $*
Він виводить другу колонку з файлу, ім’я якого було передано в якості параметру. Наприклад:
%
% cat tfile
one two three four five six seven
one1 two1 three1 four1 five six seven
% ./sc1 tfile
two
two1
%
Але навіть такий короткий скрипт можна ще зменшити. По-перше, видалимо заголовок:
awk '
{ print $2 }
' $*
Ну а по-друге, оскільки всю роботу виконує awk, можна зразу вказати на нього:
#!/usr/bin/awk -f
{ print $2 }
Обидва варіанти видають той же самий результат, що й початковий скрипт. Щоб проаналізувати час виконання, кожний з них довелося запустити 100 разів. Результати:
0.80user 0.61system 0:01.42elapsed 99%CPU у скрипта с заголовком #!/bin/bash
0.42user 0.42system 0:00.86elapsed 97%CPU у скрипта без заголовка
0.16user 0.26system 0:00.43elapsed 97%CPU при прямому виклику awk
Отже, “класичний” скрипт виконувався довше за всіх, а найшвидшим виявився скрипт з прямим викликом awk. Що ж, для того, щоб зрозуміти, чому саме так, звернемося до man bash, а саме до опису процесу виклику команди:
Якщо команду знайдено або назва команди містить косі риски, командний інтерпретатор виконує відповідну команду в окремому середовищі виконання. Аргумент 0 встановлюється рівним назві команди, і вона отримує параметри, що відповідають аргументам командного рядку, якщо такі були задані
Якщо виконати команду не вдалось, тому що файл не відповідає підтримуваним форматам, і цей файл не є каталогом, тоді буде зроблено висновок, що цей файл є сценарієм командного інтерпретатору (відповідно, містить команди). Для його виконання буде запущено породжений командний інтерпретатор….
Якщо текст в файлі починається з #!, решта першого рядку задає інтепретатор для програми. Командний інтерпретатор запустить вказаний інтерпретатор у операційних системах, що безпосередньо не підтримують вказаний формат виконуваного файлу. У якості аргументів командного рядку цей інтерпретатор отримає один необов’язковий агрумент, потім назву інтерпретатору з першого рядку програми, потім назву самої програми та її аргументи (якщо такі були задані).
Ага, стало ясніше. У другому випадку ядро намагалось виконати текстовий файл, не вийшло, автоматично було запущено інтерпретатор, що й виконав усі команди, які знайшлися в файлі. Хоча, чому тоді цей скрипт загалом виконувався швидше, ніж перший? дивно.
Третій випадок цікавіше. Зверніть увагу, в тексті скрипту явно не було вказано, що дані слід брати з файлу tfile. Ім’я файлу з даними буде передано при формуванні рядку виклику інтерпретатору: awk -f sc2 tfile. Ще один цікавий момент полягає у тому, що коментарі в awk-програмах теж відділяються знаком “#”, тому перший рядок файлу sc2 фактично буде проігноровано.
Для чого це можна використати? Важко сказати. Можна створити пару веселих приколів. Типу сценарій, який сам себе друкує: #!/bin/cat. Або навіть сценарій, що сам себе видаляє: #!/bin/rm -vf. До речі, інтерпретатор отримає лише один аргумент, тому #!/bin/rm --verbose --forse не спрацює (точніше, спрацює трохи нетак).
Більш реальні приклади:
-- #!/bin/bash -x рекомендується використовувати для налагодження (виведення додаткової інформації)
-- #!/bin/echo теж можна використовувати при налагодженні, щоб точно знати, з яким командним рядком викликано скрипт (хоча, для цього є інші засоби)
-- #!/bin/make -f файл збирання, який можна запустити. Хтозна, може комусь таке диво і знадобиться
Кроспост, текст там вдалося відформатувати однозначно краще...
Вилучити файл --somefile
Таке цікаве завдання було запропоновано якось на російському лінуксфорумі. Виконати базові операції (передивитися, редагувати, видалити) над файлом з назвою --help. Всі розуміють, що просто так вказати cat --help не вийде — програма сприйме ім'я файлу як опцію. Що ж робити?
Насправді, все просто. Є два способи вирішення проблеми, і обидва вони вказані в man rm. По-перше, можна вказати повну адресу файлу: rm ./--help. По-друге, менш відомий спосіб, можна вказати -- перед аргументом: rm -- --help.
Другий спосіб буде працювати не завжди, а лише у програмах, які для обробки переданого командного рядка використовують функцію getopt. Втім, так роблять майже всі програми, окрім найдавніших. Очевидно, через те, що сама фукнція з'явилась не так давно (за юніксовими мірками ;)). Такі старі та поважні програми, як tar, дозволяють собі мати власні правила задання опцій. Та ж сама команда tar -xvf --help має цілком нормально виконатись.
--Whirlwind 17:28, 17 липня 2008 (UTC)
не по темі: Виявилось, дописи вилучити не можна. Упс, сорі. Постараюсь виправитись, написавши щось схоже на корисне :)
тестова стаття ще один абзац тестова стаття тестова стаття
тестова стаття тестова стаття тестова стаття

