madf: (Default)
[personal profile] madf
„Ты знаешь, что производительность труда —
критерий развистости общества любого!“
АСГУ



„В психологии прянято различать две монотонии:
- развивающуюся в результате многократного повторения одних и тех же движений и поступления большого количества одинаковых сигналов в одни и те же нервные центры, т.е. информационной перегрузки ( например, работа на конвейере с мелкими операциями, когда человеку за смену приходится сотни и тысячи раз повторять одни и те же движения) ;
- вызываемую однообразием восприятия, когда приходится действовать в условиях одной и той же мало изменяющейся информации; недостаток новой информации порождает у человека так называемый «сенсорный голод» (это езда в условиях однообразной, неинтересной местности, длительное наблюдение за приборными пультами в ожидании появления редкого, но важного сигнала и т.п.); подобная монотония особенно типична для водителей.

Тот и другой род монотонии, хотя в одном случае ее причиной является перегрузка информацией, а в другом, наоборот, ее недостаток, переживаются примерно одинаково: как какая-то своеобразная тяжело переносимая скука, усталость, как какое-то отупление от топтания на месте, что-то вроде дурмана. Подобное состояние у водителей иногда называют «дорожный гипноз».“

© Монотонное движение.

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

Хочу розказати одну історію, пов’язану з проектом CarWash, яким я займаюсь уже шість чи сім років. Це один із найуспішніших проектів у яких я брав участь. Він зараз переживає стадію активного росту і очікує на кардинальні зміни, але мова піде не про це. У своїй роботі я слідую принципам DRY і намагаюсь автоматизувати більшість однакових монотонних дій. Тут я люблю згадувати стару історію: колись давно, коли я тільки почав заробляти собі на життя програмуванням і тільки познайомився з редактором vim, переді мною постала задача замінити у файлі з пів сотні рядків за певною схемою. Пів сотні — замало щоб писати програму для цього, але достатньо щоб навіяти смертельну нудьгу. Я знав що на цю роботу я витрачу хвилин 20, але навіть починати її не хотів. Мені було не цікаво. Тоді я вирішив написати регулярний вираз який виконає цю роботу за мене. Схема заміни рядків була не тривіальною, тому я витратив ті самі 20 хвилин на написання регулярного виразу, який зробив усю роботу за кілька мілісекунд. Тобто, робота зайняла той самий час, але я зміг уникнути монотонної праці (і багатьох помилок). Я вважаю що якщо якусь роботу може виконувати машина — нехай саме вона її і виконує. Людина у конвеєра — пережиток двадцятого сторіччя, артефакт із минулого. Машина зробить цю роботу швидше, надійніше і не допустить помилок, а її робота коштує значно менше ніж робота людини.


У проекті CarWash я займався програмним забезпеченням для „мозку“ системи — управляючого комп’ютера. ПЗ включає операційну систему (Linux), управляючу програму і з десяток допоміжних скриптів. Все це добро зберігається на карточці CompactFlash з якої і завантажується комп’ютер.

Коли проект тільки починався, мені не важко було взяти флешку, розмітити її за допомогою fdisk, відформатувати, „залити“ операціонку, встановити завантажувач, зібрати і залити управляючу програму, залити ключі для OpenVPN і внести необхідні зміни у конфігураційні файли. Потім я її тестував у стенді. Все це займало хвилин 30-40. Тоді-ж я зробив спробу зробити еталонний образ флешки щоб спростити процес, але образ виходив завеликим і процес запису його займав багато часу (сама „прошивка“ займає 20 Мб, але флешка розмічена повністю для тимчасового збереження даних статистики). Тому я просто зробив „зріз“ файлової системи.

У 2009-му обсяг замовлень виріс, і треба було „прошивати“ уже не одну-дві флешки, а двадцять-тридцять. Найбільше часу займало тестування на стенді, тому ним довелось пожертвувати. Тим паче що управляюча програма давно стабілізувалась, а „залізо“ все стандартне. Та всі інші етапи процесу все ще виконувались вручну. Звісно, за такої великої кількості однакових кроків помилки неминучі, контроль і різноманітні перевірки займають багато часу. Як раз тоді я збирався покинути проект і в процесі „передачі досвіду“ було сформовано файлик на суміші англійської і POSIX Shell, який описував процес створення прошивки. Покинути проект не вийшло, але той файлик швидко перетворився на 2 скрипти. Один готував флешку: розмічав, форматував, „заливав“ базову систему. Інший конфігурував її.

Перша проблема, з якою мені довелося стикнутись в процесі написання цих скриптів — це автоматична розмітка диску. Власне це і не проблема зовсім, „всё уже украдено до нас“. sfdisk як раз і створено для автоматизації цього процесу. Створення двох розділів, на 64 Мб і на весь простір що залишився виглядає так:
/sbin/sfdisk -q -uM $DEVICE <<EOF
,64,L,
,,L,
EOF

Наступна проблема — встановлення завантажувача. У якості останнього виступає grub. Стандартна утиліта grub-install працювати відмовилась, тому довелось використовувати grub у режимі batch:
/sbin/grub --batch <<EOF
root (hd2,0)
setup (hd2)
quit
EOF

Очевидна проблема тут — прив’язка до (hd2). Зміни у дисковій підсистемі чи просто вставлена ще одна флешка призведуть до того що завантажувач буде встановлено не туди. А скоріше взагалі не буде встановлено. Тому це шматок коду довгий час був закоментований.

Ще одна проблема — як змінити рутовий пароль до прошивки. Із міркувань безпеки, один і той самий рутовий пароль використовується тільки в рамках одного об’єкту. На різних об’єктах паролі різні. Є така утиліта, chpasswd. Вона читає пари <login:password> із stdin і пише у shadow. От тільки треба цю утиліту запускати у chroot-environment. Тому було написано ще один скрипт:
#!/bin/sh

echo "root:$1" | /sbin/chpasswd

Який запускається так:
/bin/chroot /mnt/flash1 /tmp/chpass.sh $RPASSWORD


Ця зв’язка скриптів прожила досить довго. Тепер процес створення прошивки став значно коротше: запускаємо перший скрипт, встановлюємо завантажувач, запускаємо другий скрипт, перевіряємо що прошивка завантажується за допомогою qemu. Час створення прошивки скоротився до 5-10 хвилин. Але і кількість замовлень виросла. Коли створюєш 50 прошивок, навіть у цих чотирьох командах стало легко заплутатись. Тим паче почали лізти помилки від sfdisk на кшталт „Device or resource is busy“, хоча пристрій ніхто не займав. Єдине що допомагало у цьому випадку – видалення всіх розділів з флешки і запуск скрипта наново.

Коли мені прийшло замовлення на 100 прошивок я вирішив покінчити з рабською працею і автоматизувати всі операції, включаючи встановлення завантажувача і тестування. Перш за все треба було добитись працездатності grub-install. У chroot-environment він просто не знаходив потрібного пристрою, видаючи щось таке: „Could not find device for /boot: Not found or not a block device.“. grub-install це просто shell-скрипт, і помилка прилітала звідси:
# Usage: find_device file                                                       
# Find block device on which the file resides.                                  
find_device () {                                                                
    # For now, this uses the program `df' to get the device name, but is        
    # this really portable?                                                     
    tmp_fname=`df $1/ | sed -n 's%.*\(/dev/[^   ]*\).*%\1%p'`                   
                                                                                
    if test -z "$tmp_fname"; then                                               
        echo "Could not find device for $1" 2>&1                                
        exit 1                                                                  
    fi                                                                          
                                                                                
        tmp_fname=`resolve_symlink $tmp_fname`                                  
                                                                                
    echo "$tmp_fname"                                                           
}

Утиліта df у chroot-environment не показувала потрібного розділу. Вона є частиною coreutils, але у прошивці сидить busybox, тому я поліз у нього. Реалізація df звідти використовує find_mount_point із libbb. Та в свою чергу розбирає файл /etc/mtab який і не файл насправді, я символічне посилання на /proc/mounts. Найпростіший вихід із ситуації — підсунути grub-install згенерований mtab:
/bin/mv /mnt/flash1/etc/mtab /mnt/flash1/etc/mtab.bak
echo "/dev/${DEVICE}1 / rootfs rw 0 0" > /mnt/flash1/etc/mtab
mount --bind /dev /mnt/flash1/dev
mount -t proc proc /mnt/flash1/proc

/bin/chroot /mnt/flash1 /sbin/grub-install --recheck ${DEVICE}

/bin/umount /mnt/flash1/proc
/bin/umount /mnt/flash1/dev
/bin/mv /mnt/flash1/etc/mtab.bak /mnt/flash1/etc/mtab


Проблему з „Device or resource is busy“ я вирішив додаванням ключа --no-reread до sfdisk.

Перевірку того що флешка завантажується я планував зробити наступним чином: запустити її під qemu, підчепитись по ssh за допомогою expect і потім вимкнути її. Але штатна прошивка не вміє вимикати живлення компа (немає підтримки ACPI у ядрі), не зможе вимкнути qemu і скрипт доведеться зупиняти руками. Я уже хотів перезбирати ядро прошивки, але згадав що qemu можна запустити у текстовому режимі. І знайшов готовий скрипт для expect що вміє керувати qemu. Його довелось трошки модифікувати, зараз він виглядає так:
#!/usr/bin/expect -f

#Start the guest VM
spawn qemu-system-i386 -curses -hdc [lindex $argv 0]

expect "GNU GRUB"
send -- "\r"

#Login process
expect "login: "
#Enter username
send -- "root\r"

#Enter Password
expect "Password: "
send -- [lindex $argv 1]
send -- "\r"
                                                                                
#poweroff the Guest VM
expect "# "
send -- "poweroff\r"

expect "System halted."
close


Тепер прошивка створюється автоматично, одним скриптом, з мінімальною участю людини: вставити флешку, запустити скрипт. На все уходить близько двох хвилин часу.

Правда, залишається проблема з підготовкою даних для прошивки: заведення облікових записів у базі, генерація ключів... Тут, насправді, просто неоране поле роботи. Скрипт що створює прошивку бере дані із файлів. Файли дублюють інформацію із бази. Колись я використовував ці файли для ведення обліку прошивок, тепер у них немає сенсу. Але у базі немає API за допомогою якого скрипт зміг би витягнути потрібну інформацію, тому доводиться і досі дублювати цю інформацію (і це навіть допомогло один раз). Крім того можна додати тестування працездатності управляючої програми, адже qemu дозволяє „причепити“ на COM-порт будь-який скрипт чи програму. Також можна перевірити працездатність VPN.

Зараз потрібно вручну вказувати який пристрій відповідає флешці, але у мене є ідеї як можна застосувати udisksctl для автоматичного визначення необхідного пристрою. Або хоча б для контролю того що пристрій відповідає флешці формату CompactFlash (одного разу я випадково прошив свою власну флешку з вельми цінною інформацією).

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


Мораль проста: нехай роботу працюють роботи, а людині залиште творчість.

Profile

madf: (Default)
madf

April 2018

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 7th, 2026 09:14 pm
Powered by Dreamwidth Studios