Вирішення проблем додатків за допомогою трасування

Дослідження програм за допомогою truss

додатків

Системні адміністратори часто цікавляться механізмом роботи програм. З першого погляду ясно тільки одне: додаток начебто запускається, а потім зупиняється або зависає без жодних пояснень. Ні системні журнальні файли, ні технічна документація не можуть допомогти. Трасування програми - така дія в такому випадку.

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

Класична проблема з правами доступу до файлу

Один клас проблем, який постійно переслідує системних адміністраторів, - це право доступу до файлу. Додаток, напевно, відкриє якісь файли, щоб виконати свою роботу. Якщо операція відкриття файлу буде невдалою, програма повинна повідомити про це адміністратора. Однак розробники часто забувають перевірити результати роботи функцій або виконують перевірку, але забувають про обробку помилок. Наприклад, ось інформація, яка виводиться програмою при невдалій спробі відкрити файл:

Після запуску фіктивної програми openapp було отримано марне та неправильне повідомлення про помилку: This should never happen! . Настав час використовувати truss. У лістингу 1 показано ту ж програму, що працює під командою truss , яка показує виклики функції, зроблені програмою до зовнішніх бібліотек.

Лістинг 1. Додаток openapp виконується під truss

Кожен рядок виведеної інформації являє собою виклик функції, зроблений додатком, та його результат, якщо можливо. (Докладно дізнатися про те, щоробить кожна функція, що викликається, можна за допомогою довідкової системи man для конкретної функції, наприклад, man open .) Для того щоб знайти виклик, можливо, що є причиною неполадок програми, часто буває простіше почати з кінця (або так близько, як тільки можливо до того місцем, де виникає проблема). Наприклад, вам відомо, що програма виводить This should never happen! і це повідомлення з'являється десь ближче до кінця, що виводиться утилітою truss інформації. Якщо ви знайшли таке повідомлення, проаналізувавши висновок команди truss , напевно зможете виявити причину проблеми.

Прокрутивши вгору повідомлення про помилку, можна звернути увагу на рядок open("/etc/configfile". , який не тільки стосується цієї проблеми, але й повертає Err#13 EACCES . Якщо подивитися на опис функції open() (команда man open ), очевидно, що метою цієї функції є відкрити файл - у цьому випадку /etc/configfile - а значення EACCES, що повертається, означає те, що проблема пов'язана з правами доступу до цього. має право читати цей файл, а потім можна застосувати команду chmod , і програма почне працювати правильно.

У виведенні в лістингу 1 показані два інші виклики - open() і stat(), які повертають помилку. Багато викликів, включаючи два, що викликають помилки, на початку роботи програми виконуються операційною системою по відношенню до цієї програми. Тільки досвід може допомогти визначити коли помилки нешкідливі, а коли ні. У цьому випадку є дві помилки і слідом за ними йдуть три рядки, в яких робиться спроба знайти libc.so.1. Про проблеми із спільно використовуваними бібліотеками буде розказано пізніше.

Додаток не запускається

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

У першому прикладі було показано очевидний зв'язок між системним викликом (джерелом проблеми) та файлом; Наступний приклад буде трохи складнішим. Лістинг 2 показує некоректно працююче застосування getlock, що працює спільно з truss .

Лістинг 2. getlock під наглядом truss

Останній виклик fcntl() відзначений як sleeping (засипає), тому що функція блокується. Це означає, що функція чекає, поки щось трапиться, і ядро ​​переводить цей процес у сплячий стан, поки не станеться очікувана подія. Щоб дізнатися, яка подія очікується, необхідно вивчити функцію fcntl() .

Сторінка допомоги man для fcntl() ( man fcntl ) описує функцію як "file control" (керування файлами) у Solaris та "manipulate file descriptor" (керування файловими дескрипторами) у Linux. У будь-якому випадку fcntl() вимагає файлового дескриптора, який є цілим числом, що описує файл, відкритий процесом, дію, яка буде виконана при отриманні файлового дескриптора, і будь-які інші аргументи, які можуть знадобитися функції. У лістингу 2 файловий дескриптор дорівнює 3, а команда F_SETLKW. (Число 0xFFBFFD60 є вказівником на структуру даних, яка в даний момент інтересу не представляє.) Рухаючись далі, можна з'ясувати, щоF_SETLKW відкриває блокування на файлі і чекає, поки це блокування не буде отримано.

З першого прикладу із системним викликом open() видно, що успішний виклик повертає файловий дескриптор. У інформації, що виводиться truss у лістингу 2, є два випадки, коли результатом системного виклику open() буде 3. Оскільки файлові дескриптори повторно використовуються після того, як їх закрили, функція open() розташована прямо над fcntl() , яка працює з /tmp /lockfile. Утиліта типу lsof показує список процесів, які містять будь-які файли відкритими. Таким чином, можна знайти процес у каталозі /proc, який тримає цей файл відкритим. Однак зазвичай файл блокується з добрих намірів, наприклад, щоб обмежити кількість екземплярів програм або налаштувати програму, щоб вона виконувалася в специфічному для користувача каталозі.

Робота з процесами, що вже виконують

Іноді, коли відбувається помилка, програма вже працює. Можливість запускати працюючий процес під truss може бути корисною. Наприклад, з інформації, що виводиться утилітою top, видно, що один процес споживає 95% потужності CPU протягом деякого часу, як показано в лістингу 3.

Лістинг 3. top виводить найбільш ресурсомісткий процес

Застосування опції -p з truss дає можливість власнику процесу або root (адміністратору) приєднати трасувальник до виконуваного процесу та відстежити системні виклики. Для цього потрібно знати PID. У лістингу 3 PID відповідає 11063. Лістинг 4 показує системні дзвінки для досліджуваної програми.

Лістинг 4. Інформація, що виводиться truss , після приєднання до працюючого процесу

Сторінка man sendto каже, що функція sendto() використовується, щоб надсилати повідомлення від сокету (зазвичай це виконується черезмережа). Висновок truss показує файловий дескриптор (перша цифра 3) та дані, що були передані (abc). Аналіз процесу за допомогою інструмента snoop або tcpdump покаже велику кількість трафіку, призначеного для будь-якого хоста, що, звичайно, не є свідченням програми, що коректно працює.

Зазначимо, що truss не спроможний у цьому випадку відобразити створення файлового дескриптора 3, оскільки був приєднаний до програми після того, як дескриптор був створений. Це є обмеженням, що виникає при приєднанні до виконуваного процесу утиліти truss, тому для збору більш детальної інформації слід використовувати інші інструменти, наприклад, аналізатор пакетів (packet analyzer), перш ніж робити висновки.

Фільтрування інформації, що виводиться

Оскільки grep можна використовувати для обробки інформації у виводі, буде простіше конфігурувати truss таким чином, щоб спостерігати лише окремі виклики. Ця практика дуже популярна у випадку, коли намагаються визначити, як працює програма (наприклад, які конфігураційні файли використовує цю програму). У цьому випадку системні виклики open() та stat() вказують на всі файли, які намагається відкрити програму.

Для відкриття файлу використовується open(), для отримання інформації про файл використовується stat(). Часто програма шукає файл за допомогою серії дзвінків stat() , а потім відкриває цей файл.

Щоб відфільтрувати системні дзвінки, використовується опція -t разом із truss . Для strace під Linux використовується -e. У будь-якому випадку необхідно передати в командний рядок список системних дзвінків, відокремлених один від одного комою. Поставивши знак оклику ( ! ) перед списком, можна відфільтрувати потрібну інформацію. Лістинг 5 показує, яктестовий додаток шукає файл конфігурації.

Лістинг 5. Фільтр, накладений на виведення truss , щоб відображати лише функції stat() та open()

Висновок

Незалежно від того, що використовує операційна система - truss, strace, trace або щось інше, можливість спостерігати за деталями виконання програми є потужним інструментом для усунення збоїв програмного забезпечення. Узагальнено цю методику можна описати так:

  1. Опис проблеми.
  2. Трасування програми.
  3. Почати з позиції, в якій проявляється проблема, та дослідити системні виклики; Щоб визначити проблему, можна використовувати довідкову систему man для інтерпретації системних викликів.
  4. Виправити поведінку та відтестувати програму.

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

Ресурси для скачування

Схожі теми

Коментарі