GNU/Linux

РОЗДІЛ З НОТАТКАМИ ПРО ЛІНУКС

Jan 29, 2026

Суброзділ GNU/Linux

csignal

У операційних системах типу Unix (Linux, macOS) сигнали — це форма міжпроцесної взаємодії (IPC). Хоча більшість сигналів мають конкретне призначення (як-от SIGKILL для зупинки процесу), існують спеціальні сигнали, зарезервовані саме для користувацьких потреб.

#NAMEC/C++htop
1HUPSIGHUPSIGHUP“Hangup” (відбій). Раніше означав розрив зв’язку з терміналом. Зараз часто використовується для того, щоб змусити фонові програми (демони) перечитати конфігураційні файли.
2INTSIGINTSIGINT“Interrupt” (переривання). Виникає, коли ви натискаєте Ctrl+C.
3QUITSIGQUITSIGQUITСхожий на INT (натискання Ctrl+\), але змушує програму створити “core dump” (знімок пам’яті) для налагодження.
4ILLSIGILLSIGILL“Illegal Instruction”. Програма намагається виконати команду, яку процесор не розуміє.
5TRAPSIGTRAPSIGTRAPВикористовується налагоджувачами (debugger) для встановлення точок зупинки (breakpoints).
6ABRTSIGSIG“Abort”. Посилається самою програмою через функцію abort(), зазвичай при критичній помилці в коді.
7BUS-SIGBUSПомилка шини. Програма намагається отримати доступ за неправильною адресою пам’яті.
8FPESIGFPESIGFPE“Floating Point Exception”. Виникає при помилковій математичній операції, наприклад, при діленні на нуль.
9KILLSIGKILLSIGKILLНайпотужніший сигнал. Він миттєво вбиває процес. Його неможливо проігнорувати або перехопити через код.
10USR1-SIGUSR1Ці сигнали не мають визначеного системою значення.
11SEGVSIGSEGVSIGSEGV“Segmentation Fault”. Найвідоміша помилка програміста — спроба звернутися до пам’яті, яка програмі не належить.
12USR2-SIGUSR2Ці сигнали не мають визначеного системою значення.
13PIPESIGPIPESIGPIPEВиникає, коли програма намагається писати в “трубу” (pipe), інший кінець якої вже закритий.
14ALRMSIGALRMSIGALRMСигнал-будильник. Використовується для таймерів.
15TERMSIGTERMSIGTERM“Terminate”. Стандартний сигнал для ввічливого прохання до програми завершити роботу. На відміну від KILL, програма може його “спіймати” і встигнути зберегти дані.
16STKFLT-SIGSTKFLTПомилка стека на співпроцесорі (зараз майже не використовується).
17CHLD-SIGCHLD“Child”. Надсилається батьківському процесу, коли його дочірній процес завершується або зупиняється.
18CONT-SIGCONT“Continue”. Наказує зупиненому процесу продовжити роботу.
19STOP-SIGSTOPЗупиняє (ставить на паузу) процес. Як і KILL, його не можна перехопити.
20TSTP-SIGTSTP“Terminal Stop”. Виникає при натисканні Ctrl+Z. Зупиняє процес, але його можна перехопити.
21SIGTTIN-SIGTTINФоновий процес хоче read() з термінала.
22SIGTTOU-SIGTTOUФоновий процес хоче write() в термінал (якщо увімкнено tostop)
23URG-SIGURGТермінові дані в мережевому сокеті.
24XCPU-SIGXCPUПрограма перевищила ліміт часу роботи процесора.
25XFSZ-SIGXFSZПрограма намагається створити файл, більший за дозволений ліміт.
26VTALRM-SIGVTALRMВіртуальний таймер (враховує тільки час, коли процес працював).
27PROF-SIGPROFВикористовується для профайлінгу (вимірювання швидкості роботи коду).
28WINCH-SIGWINCHЗміна розміру вікна термінала.
29POLL-SIGPOLLПодія введення-виведення.
30PWR-SIGPWRПомилка живлення (наприклад, коли ДБЖ повідомляє про розряд батареї).
31SYS-SIGSYSНеправильний системний виклик.
33reserved-SIGCANCELВикористовуються NPTL (Native POSIX Thread Library). Використовується бібліотекою для скасування потоків.
33reserved-SIGSETXIDВикористовуються NPTL (Native POSIX Thread Library).Використовується для синхронізації змін ідентифікаторів користувача/групи (UID/GID) між усіма потоками одного процесу.
34-SIGRTMINSIGRTMIN-
35--SIGRTMIN+1-
..--SIGRTMIN+..-
64-SIGRTMAXSIGRTMIN+30-

CMakeLists.txt

project(sig)

add_executable(alpha alpha.cpp)
add_executable(betta betta.cpp)

file(WRITE ${CMAKE_BINARY_DIR}/.gitignore "*\n*.*")

alpha.cpp

#include <csignal>
#include <fstream>
#include <iostream>
#include <unistd.h>

// Обробник сигналів з параметром
void handle_signal(int sig, siginfo_t *info, void *context) {
  std::cout << "\n[Альфа] Отримано сигнал з параметром: "
            << info->si_value.sival_int << std::endl;
}

int main() {
  pid_t my_pid = getpid();
  std::cout << "Альфа запущена. PID: " << my_pid << std::endl;

  // 1. Записуємо свій PID
  std::ofstream out("alpha.pid");
  out << my_pid;
  out.close();

  // 2. Налаштовуємо обробник
  struct sigaction sa;
  sa.sa_sigaction = handle_signal;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sigaction(SIGRTMIN, &sa, NULL);

  std::cout << "Чекаю на файл beta.pid та сигнали..." << std::endl;

  // 3. Цикл взаємодії
  while (true) {
    std::ifstream in("beta.pid");
    pid_t target_pid;
    if (in >> target_pid) {
      int val;
      std::cout << "Введіть число для надсилання Беті (або 0 для виходу): ";
      std::cin >> val;
      if (val == 0)
        break;

      sigval sv;
      sv.sival_int = val;
      sigqueue(target_pid, SIGRTMIN, sv);
    }
    in.close();
    sleep(1);
  }

  unlink("alpha.pid"); // Видаляємо файл при виході
  return 0;
}

betta.cpp

#include <csignal>
#include <fstream>
#include <iostream>
#include <unistd.h>

void handle_signal(int sig, siginfo_t *info, void *context) {
  std::cout << "\n[Бета] Отримано сигнал з параметром: "
            << info->si_value.sival_int << std::endl;
}

int main() {
  pid_t my_pid = getpid();
  std::cout << "Бета запущена. PID: " << my_pid << std::endl;

  // 1. Записуємо свій PID
  std::ofstream out("beta.pid");
  out << my_pid;
  out.close();

  // 2. Налаштовуємо обробник
  struct sigaction sa;
  sa.sa_sigaction = handle_signal;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_SIGINFO;
  sigaction(SIGRTMIN, &sa, NULL);

  // 3. Читаємо PID Альфи та надсилаємо вітання
  std::cout << "Шукаю Альфу..." << std::endl;
  while (true) {
    std::ifstream in("alpha.pid");
    pid_t target_pid;
    if (in >> target_pid) {
      std::cout << "Альфу знайдено (PID: " << target_pid
                << "). Насилаю '777'..." << std::endl;
      sigval sv;
      sv.sival_int = 777;
      sigqueue(target_pid, SIGRTMIN, sv);
      break;
    }
    sleep(1);
  }

  // Залишаємося працювати для прийому сигналів
  while (true)
    pause();

  unlink("beta.pid");
  return 0;
}

systemctl

systemctl є головним інструментом для керування системою ініціалізації systemd. Коли ви віддаєте команду systemctl, вона не просто “вбиває” процес, а намагається керувати ним цивілізовано.

systemctl stop \[service\]

Це найчастіша операція. Systemd діє за певним алгоритмом:

  1. SIGTERM (15). Це “ввічливе” прохання завершити роботу. Програма отримує сигнал і має час, щоб зберегти файли, закрити з’єднання з базою даних і вийти самостійно.
  2. Очікування (Timeout). Systemd чекає (за замовчуванням 90 секунд).
  3. SIGKILL (9). Якщо програма не закрилася за відведений час, systemd надсилає “контрольний постріл”, який завершує процес миттєво без збереження даних.

systemctl restart \[service\]

Працює точно так само, як stop, а після повного завершення процесу запускає його знову.

systemctl reload \[service\]

Ця команда не зупиняє програму. Вона зазвичай надсилає сигнал SIGHUP (1). Більшість серверів (як-от Nginx або Apache) налаштовані так, що при отриманні SIGHUP вони перечитують свої конфігураційні файли, не перериваючи обслуговування користувачів.

Команда systemctlСигнал за замовчуваннямМета
stopSIGTERMБезпечне завершення.
killSIGTERM(або інший вказаний)Негайне надсилання сигналу всій групі процесів.
reloadSIGHUPОновлення конфігурації без перезапуску.
(якщо завис)SIGKILLПримусове завершення після таймауту.

Налаштування сигналів у .service файлі

  • KillSignal= Вказує, який сигнал надіслати першим при зупинці (systemctl stop). За замовчуванням це SIGTERM. Ви можете змінити його, наприклад, на SIGQUIT або SIGUSR1.
  • RestartKillSignal= Який сигнал використовувати при перезавантаженні.
  • FinalKillSignal= Який сигнал надіслати, якщо програма не закрилася вчасно (за замовчуванням SIGKILL). Його неможливо змінити на щось, що можна ігнорувати.
  • ExecReload= Тут ви можете вказати команду, яка виконується при systemctl reload. Часто туди пишуть /bin/kill -HUP $MAINPID.
[Unit]
Description=Мій кастомний C++ сервіс

[Service]
ExecStart=/usr/local/bin/my_app
# Змінюємо сигнал зупинки на SIGINT (як Ctrl+C)
KillSignal=SIGINT
# Даємо програмі 20 секунд на завершення перед примусовим вбивством
TimeoutStopSec=20
# Якщо натиснули reload, надіслати сигнал реального часу 34
ExecReload=/bin/kill -34 $MAINPID

[Install]
WantedBy=multi-user.target

Як перевірити, що програма отримала сигнал від systemd?

Коли ви зміните файл сервісу, не забудьте оновити конфігурацію systemd:

sudo systemctl daemon-reload

sudo systemctl restart my_service

Тепер ви можете перевірити логи вашої програми в реальному часі:

journalctl -u my_service -f

Bash yaml parser

yb - bash парсер YAML

yb надає чисте Bash рішення для парсингу YAML.

Використання

yb [-h|-a|-c|-q|-r|-A-C-d-F-K-l-L-R-n-T] [-f <файл>|-o <об'єкт>] [-k <ключ>] [-v <значення>|-O <значення об'єкта>]

Приклади

./yb -f файл.yaml -k "ключ.дочірнійключ"

З репозиторію ви можете швидко спробувати так:

./yb -f tests/user.yaml -k "yb"

Створення ключів:

./yb -af tests/user.yaml -k "new.key"

додати вбудоване значення:

./yb -af tests/user.yaml -k "new.key" -v "one, two"

змінити його:

./yb -cf tests/user.yaml -k "new.key" -v "three"

додати значення списку:

./yb -af tests/user.yaml -k "new.- list" -v "- one - two"

додати ASCII всередині ключа каналу:

./yb -af tests/user.yaml -k "new.ascii|" -v "|> ___ _ |> \ \// |> \ / |> / / |> /_/"

Маніпулювати YAML як змінною bash:

# Рекомендується використовувати опцію '-R' raw для отримання вмісту без колірних кодів
my_YAML=$(./yb -f tests/user.yaml -k "new")
my_YAML=$(./yb -ao "${my_YAML}" -k "in_memory" -v "true")

Додати його до файлу:

./yb -af tests/user.yaml -k "new.copy" -o "${my_YAML}"

Видалити одне значення:

./yb -rf tests/user.yaml -k "new.- list" -v "- one"

або видалити все:

./yb -rf tests/user.yaml -k "new"

Встановлення

З репозиторію

З репозиторію
git clone https://github.com/t0pd4wn/yb.git
cd yb
chmod +x yb
git clone https://github.com/Sam4uk/yb.git
cd yb
chmod +x yb

yb можна використовувати безпосередньо з папки репозиторію або скопіювати та використовувати як окремий файл у проекті.

З URL-адреси

Ви можете використовувати цю команду для безпосереднього завантаження скрипта yb, де це необхідно:

З URL-адреси
bash <(echo "https://gitlab.com/t0pd4wn/yb/-/raw/main/yb"|(read l; wget $l || curl $l >yb)) && chmod +x yb;
bash <(echo "http://sam4uk.github.io/yb/yb"|(read l; wget $l || curl $l >yb)) && chmod +x yb;

Якщо ви хочете, щоб yb був доступний для всієї системи, виконайте цю команду з папки репозиторію:

sudo cp yb /usr/local/bin/

Однорядковий код

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

Однорядковий код
bash <(echo "https://gitlab.com/t0pd4wn/yb/-/raw/main/yb"|(read l; wget $l || curl $l >yb)) && chmod +x yb;
bash <(echo "http://sam4uk.github.io/yb/yb"|(read l; wget $l || curl $l >yb)) && chmod +x yb;

Ви можете використати цю команду для встановлення yb у вашу систему одним рядком:

Однорядковий код
bash <(echo "https://gitlab.com/t0pd4wn/yb/-/raw/main/yb"|(read l; wget $l || curl $l >yb)) && chmod +x yb && sudo cp yb /usr/local/bin && rm yb;
bash <(echo "http://sam4uk.github.io/yb/yb"|(read l; wget $l || curl $l >yb)) && chmod +x yb && sudo cp yb /usr/local/bin && rm yb;
There may be pirates

У свій форк я додав можливість завантаження парсеру у форматі deb пакету який можна завантажити за цим посиланням

Параметри

Параметри yb поділяються на 3 типи:

  • action: параметри дії виконуються з файлом і не сумісні один з одним. Вони сумісні з input, але не з format.
  • input: параметри введення є параметрами, що встановлюються користувачем, і сумісні один з одним. Вони сумісні як з action, так і з format.
  • input: параметри форматування виводять вивід різними способами. Вони сумісні один з одним, з типом input, але не з типом action.
ОпціяІм’яТипОписПрикладПримітки
-aaddactionДодає ключ(и), значення(я) або обидва.yb -f "file.yaml" -a -k "key" -v "value"
-cchangeactionЗмінює значення(я).yb -f "file.yaml" -c -k "key" -v "new_value"
-qqueryactionВиводить true або false, якщо ключ(и), значення(я) або обидва присутні чи ні.yb -f "file.yaml" -q -k "key"Для отримання значення каналу -v 'значення каналу' рекомендується використовувати одинарні лапки.
-rremoveactionВидаляє ключ(и), значення(я) або обидва.yb -f "файл.yaml" -r -k "ключ" -v "значення"Для видалення значення каналу -v 'значення каналу' рекомендується використовувати одинарні лапки.
-ffileinputшлях до файлу YAML.yb -f "файл.yaml"Файл можна представити без опції -f, як опцію $1. -f та -c несумісні один з одним.
-oobjectinputоб’єкт YAML.yb -o "${YAML_object}"Об’єкт YAML можна використовувати з усіма діями. -f та -o сумісні між собою, лише під час додавання об’єкта до файлу.
-Oobject valueinputзначення об’єкта YAML.yb -f "file.yaml" -O "${YAML_object}"Об’єкт YAML можна використовувати з дією -a.
-kkeyinputШлях вибору ключів.yb -f "file.yaml" -k "ключ"Підтримує ключі у форматі:key, key.childkey, - list-key, pipe-key|. Можна вказати кілька ключів з роздільником ..
-vvalueinputЗначення, які потрібно додати, видалити, запитати або змінити.yb -f "file.yaml" -k "ключ" -v "значення"Підтримує значення у форматі: value, - list-value, |> pipe-value.
-AarrayформатВиводить вивід у вигляді масиву bash.yb -f "file.yaml" -A -k "key"Забезпечить інше форматування, якщо використовувати з -F або -d.
-CcolorsformatПримусово використовує кольори у нетермінальному виводі.yb -Cf "file.yaml" -A -k "key"
-ddepthformatЗабезпечує вихід з оригінальною глибиною.yb -f "file.yaml" -d -k "key.childkey" -v "new_value"
-FformatformatДрукує відформатований вивід для представлення деревоподібності в рядку.yb -f "file.yaml" -F -k "key"Забезпечить інше форматування, якщо використовувати з -A або -d.
-Kkeys ключіformatДрукує лише ключі.yb -Kf "file.yaml" -k "key"
-llineformatДрукує { {line}} у кожному рядку.yb -f "file.yaml" -l -k "key"
-LlevelformatДрукує { {<номер рівня>} } у кожному рядку.yb -f "file.yaml" -L -k "key"
-RrawformatДрукує вивід без доданих кольорів, коментарів та порожніх рядків.yb -f "file.yaml" -R -k "key"
-nnumberformatДрукує { {<номер рядка>} } на кожному рядку.yb -f "file.yaml" -n -k "key"
-TtypeformatДрукує тип значення.yb -f "file.yaml" -T -k "key"Підтримує null, boolean, integer, floating number, string.
-sspacesDeprecatedВибір кількості пробілів.

Підтримка YAML

yb забезпечує базову підтримку YAML для редагування та читання YAML-файлу. Починаючи з версії 0.9, yb не підтримує розширені функції, такі як пошук на основі груп, прив’язки, псевдоніми та перевизначення.

Розробка

Повні вихідні коди доступні в папці /src/. Версія, що знаходиться на кореневому рівні, зібрана за допомогою скрипта /src/tools/dist.sh.

Тести

Простий набір тестів доступний у папці tests/. Він представляє різні варіанти використання yb.

Щоб запустити його, виконайте команду нижче з кореневого рівня репозиторію:

./tests/tests.sh

Ви можете надати додатковий параметр для вибору парсера (наприклад, під час розробки):

./tests/tests.sh "./src/yb.dev"

Дякую

Всім вам, YAML-івцям!

Зроблено t0pd4wn на Bash.

Створення власного debian пакету

Огляд

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

Офіційний спосіб створення пакету включає багато кроків і процесів. У цій шпаргалці ми розглянемо простіший спосіб створення цих пакетів. Однак офіційний спосіб створення упаковки є ідеальним і рекомендованим для виробничих цілей.

Підготовка файлів

Структура пакета .deb

У дистрибутивах на основі Debian одним із способів встановлення програм є завантаження файлу пакета .deb і використання команди dpkg для його встановлення . Цей «пакет deb» — це архів двійкових і конфігураційних файлів, пов’язаних із програмним додатком. Усі файли всередині архіву зберігаються в певній структурі папок.

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

Ця інструкція про створення та інсталяцію власного debian пакету

Архітектури

Linux

ArchitectureManufacturerStatusComments
all-Supported-
AlphaHPe (formerly HP, Compaq, Digital)Unofficial
ArmHundredsDeadNetWinder, NSLU2, …
ArmelHundredsSupportedQNAP, ?SheevaPlug, Raspberry Pi 1
armhfHundredsSupportedArm v7 32-bit systems; for kernel support see DebianKernel/ARMMP
arm64HundredsSupportedArm v8 64-bit systems
hppaHPe (formerly HP)UnofficialHP Precision Architecture
i386Intel, AMD, Cyrix, NSC, Transmeta, VIASupportedThe original x86 platform. Now requires “686” class CPU.
amd64AMD, Intel, VIASupportedalso known as em64t or x86-64.
ia64Intel, HPeDeadItanium (not Intel Core series)
m68kFreescale (formerly Motorola)UnofficialAmiga, !AtariST, very old Macintoshes, some old Sun hardware (sun3)
mipsCavium, Wave Computing (formerly Imagination, MIPS)DeadBig-endian 32-bit
mipselCavium, Loongson, Wave Computing (formerly Imagination, MIPS)DeadLittle-endian 32-bit
mips64elCavium, Loongson, Wave Computing (formerly Imagination, MIPS)SupportedLittle-endian 64-bit
PowerPCIBM, Freescale (formerly Motorola)UnofficialOld Macintoshes
PowerSPEIBM, Freescale (formerly Motorola)DeadIBM “e500” cores
PPC64IBM, Freescale (formerly Motorola)UnofficialOld Macintoshes, IBM POWER systems
ppc64elIBMSupportedPOWER8, POWER9 systems
riscv64?SiFive, etc.Unofficial
s390IBMDeadBigIron - IBM mainframe platform
s390xIBMSupportedNewer BigIron - IBM mainframe platform
SH4Renesas (formerly Hitachi)Unofficial
sparc64Sun, Fujitsu, etc.Unofficial
x32AMD, Intel, VIAUnofficial32-bit ABI using x86-64 (amd64) ISA.

non-Linux

ArchitectureManufacturerStatusComments
hurd-i386see TheHurdUnofficialNot a hardware platform
hurd-amd64see TheHurdUnofficialNot a hardware platform
netbsd-i386NetBSD kernelDeadNot a hardware platform
netbsd-alphaNetBSD kernelDeadNot a hardware platform
kfreebsd-i386FreeBSD kernelDeadNot a hardware platform
kfreebsd-amd64FreeBSD kernelDeadNot a hardware platform
.
└── mypackage_1.0_all                   # Package main folder
    ├── DEBIAN
    │   ├── control                     # File with package's main info
    │   ├── postinst                    # Script executing after the install
    │   └── preinst                     # Script executing before the install
    ├── opt
    │   └── mypackage                   # Folder including our software
    │       └── open_link.sh            # Script opening browser to ubuntu.com
    └── usr
        └── share
            ├── applications
            │   └── mypackage.desktop   # File with app info in launcher
            └── icons
                └── mypackage.xpm       # Launcher app icon

Збирання

dpkg-deb --build ./mypackage_1.0_all

Інсталювання

sudo gdebi -n ./mypackage_1.0_all.deb # test (requires gdebi-core)
sudo dpkg -i ./mypackage_1.0_all.deb # install

Видалення

sudo apt autoremove mypackage