В Linux есть масса утилит, для поиска файлов. К примеру всем известный монструозный find, который умеет даже тапочки приносить.
Но что, если мне нужно просто найти какой-то файл? Использовать find для такой простой задачи, это явно стрельба из пушки по воробьям. Для таких задач, как моя, есть более изящные решения.
И это решение, утилита locate.
Утилита locate используется для поиска файлов, расположенных на машине пользователя или на сервере. Фактически она выполняет ту же работу, что и команда find, однако, ведёт поиск в собственной базе данных.
Ключевая фраза здесь - в собственной базе данных. То есть применяя утилиту locate, поиск файлов будет осуществляться не по файловой системе, как это делает find. А будет использоваться собственная база данных. Коротая позволяет искать файлы со скоростью света.
Обновление базы данных locate происходит автоматически, как правило, раз в сутки. Либо можно запустить руками командой
Давай теперь потыкаем, запускай:
Ищем файлы, которые оканчиваются на «txt»
Ключ -с = вывести общее количество найденных файлов
Полезли в кишки, заводим strace.
Переходим в папку cd /tmp и создаем подопытный файл:
Так, я нахожусь в папке tmp и у меня создан файл
Мы вызываем внешнюю команду locate, но вызываем мы ее из интерпретатора bash. Вернее её вызывает сам интерпретатор. И это накладывает свои нюансы. В нашем случае этот нюанс «Подстановка имен файлов», то есть Globbing.
Сейчас будет сложно для понимания, но чуть ниже я разжую на человеческий.
Во времена UNIX V6, существовала программа /etc/glob, которая могла раскрывать шаблоны подстановки. Очень скоро она стала встроенной функцией командной оболочки.
Но что же случилось то в итоге, почему ничего не нашлось? А произошло следующее: после того, как интерпретатор обнаружил символ «*», который является спецсимволом и соответствует любой строке, интерпретатор попытался сделать подстановку Globbing и ему это удалось.
И при вызове команды locate она получила в качестве аргументов, результат этих подстановок. Давай посмотрим наглядно что произошло. Запускаем:
execve() выполняет программу, заданную параметром filename
Возвращаемся к выводу от strace и видим что locate получила в качестве аргумента
Вот лишь по этому на экран ничего не вывелось, когда я запустил
Если ты это усвоил, то уже не наступишь на грабли. Да и strace снова немного затронули, можешь применять для дебага и смотреть что происходит внутри, после вызова той или иной команды.
Поигрались и хватит. Пошли дальше работу работать. Всех был рад видеть, пока-пока!
tags: #bash #strace #debug
—
💩 @bashdays
Но что, если мне нужно просто найти какой-то файл? Использовать find для такой простой задачи, это явно стрельба из пушки по воробьям. Для таких задач, как моя, есть более изящные решения.
И это решение, утилита locate.
Утилита locate используется для поиска файлов, расположенных на машине пользователя или на сервере. Фактически она выполняет ту же работу, что и команда find, однако, ведёт поиск в собственной базе данных.
Ключевая фраза здесь - в собственной базе данных. То есть применяя утилиту locate, поиск файлов будет осуществляться не по файловой системе, как это делает find. А будет использоваться собственная база данных. Коротая позволяет искать файлы со скоростью света.
Обновление базы данных locate происходит автоматически, как правило, раз в сутки. Либо можно запустить руками командой
updatedb.Давай теперь потыкаем, запускай:
locate txtИщем все файлы, имена которых содержат «txt». Опа, меньше чем за секунду команда нашла все подходящие файлы, которые можно было найти. А если сделать это через find, то это у меня это заняло 18 секунд. Разница очень ощутимая.
Ищем файлы, которые оканчиваются на «txt»
locate '*txt'А теперь давай посчитаем общее количество файлов, которые нашлись
locate -ic '*txt'Ключ -i = режим регистронезависимости
Ключ -с = вывести общее количество найденных файлов
Полезли в кишки, заводим strace.
Переходим в папку cd /tmp и создаем подопытный файл:
> hello.txt
Знал же что пустой файл можно создать через символ «>»? Если нет, то теперь знаешь.Так, я нахожусь в папке tmp и у меня создан файл
hello.txt запускаю:locate *txtОпа, ничего нет, как так? Мы же уже запускали ранее это, чтобы найти все файлы, которые заканчиваются на txt. Что случилось?
Мы вызываем внешнюю команду locate, но вызываем мы ее из интерпретатора bash. Вернее её вызывает сам интерпретатор. И это накладывает свои нюансы. В нашем случае этот нюанс «Подстановка имен файлов», то есть Globbing.
Сейчас будет сложно для понимания, но чуть ниже я разжую на человеческий.
Во времена UNIX V6, существовала программа /etc/glob, которая могла раскрывать шаблоны подстановки. Очень скоро она стала встроенной функцией командной оболочки.
Но что же случилось то в итоге, почему ничего не нашлось? А произошло следующее: после того, как интерпретатор обнаружил символ «*», который является спецсимволом и соответствует любой строке, интерпретатор попытался сделать подстановку Globbing и ему это удалось.
И при вызове команды locate она получила в качестве аргументов, результат этих подстановок. Давай посмотрим наглядно что произошло. Запускаем:
strace -e execve locate *txtНа выходе получаем:
execve("/usr/bin/locate", ["locate", "hello.txt"], 0x7ffe242252d8 /* 27 vars */) = 0
Опция «e» и аргумент «execve» сообщают strace, что я хочу отслеживать только системные вызовы «execve».execve() выполняет программу, заданную параметром filename
Возвращаемся к выводу от strace и видим что locate получила в качестве аргумента
hello.txt
И теперь locate будет искать файлы именно по этому шаблону, а не по тому, что мы с тобой ожидали, когда писали «*txt».Вот лишь по этому на экран ничего не вывелось, когда я запустил
locate *txt
А чтобы этого не происходило всегда используй quoting (кавычки) и будешь получать ожидаемый результат.locate '*txt'Механизм подстановки имен файлов (Globbing) на самом деле удобен, просто нужно использовать его по назначению.
Если ты это усвоил, то уже не наступишь на грабли. Да и strace снова немного затронули, можешь применять для дебага и смотреть что происходит внутри, после вызова той или иной команды.
Поигрались и хватит. Пошли дальше работу работать. Всех был рад видеть, пока-пока!
tags: #bash #strace #debug
—
Please open Telegram to view this post
VIEW IN TELEGRAM
👍157 2
Service или Systemctl?
Каждый стартует или стопает процессы как привык. Во времена динозавров когда еще не существовало
Сейчас мир изменился, появился
ㅤ
Теперь сервисами рекомендуется управлять через
Но какая в хуй разница как управлять сервисам?
И
На самом деле сейчас команда
Давай убедимся:
По итогу ты получишь:
То есть
А если глянуть исходник
То ты увидишь обычный bash скрипт в котором и происходит вся эта магия.
Если система использует SysVinit или Upstart (например, старые версии Debian, CentOS 6, Ubuntu 14.04), то service будет работать напрямую со скриптами
По бест-практикам старайся использовать
Хотя когда молодые ребята видят как ты вводишь service, у них разрывает жопу и ты автоматически присваиваешь себя к престарелым скуфам.
Как это делаю я? И так и сяк, мне вообще похуй, главное достигнут ожидаемый результат.
Кроме
А чтобы проверить какая система инициализации у тебя, вот тебе пиздатая команда:
Вот и вся наука.
А как ты рулишь сервисами? Как скуф или как современный молодой человек?
tags: #linux #debug #strace
—
🔔 @bashdays➡️ @gitgate
Каждый стартует или стопает процессы как привык. Во времена динозавров когда еще не существовало
systemd, всё сводилось к командам:service apache restart
Сейчас мир изменился, появился
systemd, но привычки остались прежними.ㅤ
Теперь сервисами рекомендуется управлять через
systemctl.Но какая в хуй разница как управлять сервисам?
И
service и systemctl выполняют по сути одно и тоже и ты по итогу получаешь ожидаемый результат.На самом деле сейчас команда
service это обёртка вокруг systemctl.Давай убедимся:
strace -f service nginx restart 2>&1 | grep execve
По итогу ты получишь:
execve("/usr/bin/systemctl", ["systemctl", "restart", "nginx.service"])То есть
service обратился к systemctl и произвел перезапуск nginx.А если глянуть исходник
service:cat /usr/sbin/service
То ты увидишь обычный bash скрипт в котором и происходит вся эта магия.
Если система использует SysVinit или Upstart (например, старые версии Debian, CentOS 6, Ubuntu 14.04), то service будет работать напрямую со скриптами
/etc/init.d/.По бест-практикам старайся использовать
systemctl. Но опять же service никто не запретит тебе использовать.Хотя когда молодые ребята видят как ты вводишь service, у них разрывает жопу и ты автоматически присваиваешь себя к престарелым скуфам.
Как это делаю я? И так и сяк, мне вообще похуй, главное достигнут ожидаемый результат.
Кроме
systemctl и service есть такие штуки для управления процессами:/etc/init.d/nginx restart
rc-service nginx restart
sv restart nginx
s6-rc -d change nginx
supervisorctl restart nginx
А чтобы проверить какая система инициализации у тебя, вот тебе пиздатая команда:
ps -p 1 -o comm=
Вот и вся наука.
А как ты рулишь сервисами? Как скуф или как современный молодой человек?
tags: #linux #debug #strace
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Если ты выполняешь план, то тебе повысят план, а не зарплату!
Пытался вчера подружить taskwarrior и s3 для синхронизации, из коробки оно вроде как только с AWS работает.
Подкинул в конфиг параметры подключение к кастомному хранилищу. Ну думаю, какая в хуй разница.
Проверяю
Мде… Всёж правильно, эндпоинт пингуется, курлится, телнетится. Описывать весь момент дебага не буду, но там конкретный такой - метод тыка был.
Ну раз обычный «метод тыка» не помогает, расчехляем
Что делает команда:
И в выхлопе находим строчку:
😀 😃 😄 😁 😅 😂 🤣 😊
😇 🙂 🙃 😉 😌 😍 🥰 😘
😗 😙 😚 😋 😛 😝 😜 🤪
🤨 🧐 🤓 😎 🤩 🥳 😏 😒
😞 😔 😟 😕 🙁 ☹️ 😣 😖
😫 😩 🥺 😢 😭 😤 😠 😡
Ну ёб твою мать! А нахуй я тогда все эти приседания с конфигом устраивал, если эта падла хуй положила и по
То есть настройка
Ну хоть проблему нашли.
Отсюда вывод: с кастомным S3 напрямую taskwarrior работать не сможет. Даже если устроить подмену хостов или сделать хак через CNAME.
А как синхронизировать-то задачи? Ооо брат, я уже написал про это отдельный пост, чуть позже закину.
Хороших тебе выходных!
🛠 #strace #debug #taskwarrior
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Пытался вчера подружить taskwarrior и s3 для синхронизации, из коробки оно вроде как только с AWS работает.
Подкинул в конфиг параметры подключение к кастомному хранилищу. Ну думаю, какая в хуй разница.
sync.backend=s3
sync.aws.region=ru-7
sync.aws.bucket=taskwarrior
sync.aws.access_key_id=aed38518013b4ab
sync.aws.secret_access_key=992570bad57
sync.aws.endpoint=s3.ru-7.storage.selcloud.ru
Проверяю
task sync init, хуй там плавал, ошибка:unhandled error: dispatch failure: io error: error trying to connect: dns error: failed to lookup address information: Name or service not known: dns error: failed to lookup address information: Name or service not known: failed to lookup address information: Name or service not known
Мде… Всёж правильно, эндпоинт пингуется, курлится, телнетится. Описывать весь момент дебага не буду, но там конкретный такой - метод тыка был.
Ну раз обычный «метод тыка» не помогает, расчехляем
strace!strace -s 200 -f -e trace=network,connect,sendto,recvfrom task sync
Что делает команда:
-s 200 — печатать до 200 байт строковых аргументов (по умолчанию strace режет строки до 32 байт). Это важно, чтобы увидеть полный URL/hostname, который передаётся в syscalls.-f — следить не только за основным процессом, но и за всеми дочерними (fork/clone)-e trace=network, connect, sendto, recvfrom — ограничиваем вывод только сетевыми вызовами: socket, connect → создание сокетов и подключения (TCP/UDP). sendto / recvfrom → передача данных (обычно видно DNS-запросы, HTTP-заголовки и т.д.).И в выхлопе находим строчку:
taskwarrior.s3.ru-7.amazonaws.com.Ну ёб твою мать! А нахуй я тогда все эти приседания с конфигом устраивал, если эта падла хуй положила и по
task diagnostic никаких ошибок не вывело.То есть настройка
sync.aws.endpoint=… вообще не учитывается — клиент жёстко строит URL по схеме AWS.Ну хоть проблему нашли.
Strace все же достаточно пиздатый инструмент.Отсюда вывод: с кастомным S3 напрямую taskwarrior работать не сможет. Даже если устроить подмену хостов или сделать хак через CNAME.
А как синхронизировать-то задачи? Ооо брат, я уже написал про это отдельный пост, чуть позже закину.
Хороших тебе выходных!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
13 58
А у нас сегодня на повестке интересная «темка» — Автоматическая очистка tmp-файлов даже после SIGTERM.
ㅤ
Пишем подопытный скрипт:
Чмодим, запускаем, ага скрипт упал на
Код выходы проверить так:
Здесь я взял синтетику, показать наглядно этот случай. Суть «темки» — подчищать за собой, при любых обстоятельствах, даже если скрипт вернул ошибку, либо завершился успешно.
Снова изобретать велосипед? Неа! Всё это работает из коробки.
В этом случае скрипт также вернет код
Нихуя непонятно, но очень интересно.
Смотри —
Давай подключим
В выхлопе видим:
То есть Bash вызывает
Почему trap срабатывает?
Если скрипт упал или получил сигнал
— в обработчике сигнала вызывается registered trap
— затем Bash падает/выходит
—
Да банально при выполнении скрипта ты нажал
Вот такие пироги!
С пятницей и хороших тебе предстоящих выходных!
🛠 #bash #debug #strace
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
ㅤ
Как говорится — Волков бояться, в лесу не ебаться!
Пишем подопытный скрипт:
#!/usr/bin/env bash
set -e
temp=$(mktemp)
echo "Создал файл: $temp"
false
echo "Удаляю файл"
rm -f "$temp"
Чмодим, запускаем, ага скрипт упал на
false, но успел создать временный файл в папке /tmp == /tmp/tmp.oWQ0HiYxSV. И он не удалился. Скрипт вернул статус == 1;Код выходы проверить так:
echo "код: $?"
Здесь я взял синтетику, показать наглядно этот случай. Суть «темки» — подчищать за собой, при любых обстоятельствах, даже если скрипт вернул ошибку, либо завершился успешно.
Снова изобретать велосипед? Неа! Всё это работает из коробки.
#!/usr/bin/env bash
set -e
temp=$(mktemp)
echo "Создал файл: $temp"
trap 'echo "Удаляю $temp"; rm -f "$temp"' EXIT
false
В этом случае скрипт также вернет код
1, но временный файл будет удалён при любом раскладе.Нихуя непонятно, но очень интересно.
Смотри —
trap вызывает rm ПРИ ВЫХОДЕ ИЗ СКРИПТА. И похуй с каким статусом был завершен скрипт. Временный файл будет гарантированно удалён.Давай подключим
strace:strace -e trace=process,signal bash -c '
tmp=$(mktemp)
trap "rm -f $tmp" EXIT
echo "tmp=$tmp"
'
В выхлопе видим:
openat(AT_FDCWD, "/tmp/tmp.Dn2qG3uK9V", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
rt_sigaction(SIGINT, {sa_handler=0x...}, NULL, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=0x...}, NULL, 8) = 0
unlink("/tmp/tmp.Dn2qG3uK9V") = 0
exit_group(0) = ?
openat(... O_EXCL) — это mktemp, создающий файл атомарноrt_sigaction() — Bash ставит ловушки для сигналовunlink() — это и есть выполнение trapexit_group(0) = ? — завершает процессТо есть Bash вызывает
rm/unlink() ДО выхода из процесса.Почему trap срабатывает?
Если скрипт упал или получил сигнал
kill -TERM <pid>, то на уровне Bash:— в обработчике сигнала вызывается registered trap
— затем Bash падает/выходит
—
trap УЖЕ успел выполнить команду очисткиtrap выполняется ДО того, как процесс отдаст SIGTERM ядру, если только ловушка для этого сигнала была установлена.Да банально при выполнении скрипта ты нажал
CTRL+C, скрипт остановился, НО временные файлы сразу подчистились.➡️ Про exit codes (коды выхода) писал тут.➡️ Про сигналы писал ранее тут и тут и тут и тут.
Вот такие пироги!
С пятницей и хороших тебе предстоящих выходных!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
5 59
Вчера в чатике интересный комментарий пролетел:
Давай покопаем глубже и посмотрим что происходит. Расчехляем лабу!
ㅤ
В первом терминале запускаем:
Во втором запускаем глазища:
Пока пусто. Теперь в первом терминале нажимаем
Получается
Теперь идем в
Но во втором терминале запускаем:
И сразу же видим что
Но это не сам файл
Этот файл, vim использует для crash recovery, undo history, file already open, incremental writes и т.п. Получается что vim постоянно держит открытый swap, а не исходный файл.
Если выполнить:
То увидим всю подноготную этого процесса включая дескрипторы.
Ну и финт ушами. В первом терминале выполняем:
Во втором:
И видим что
А если все то же самое проделать с
Вот тут уже можно почесать репу, получается
Схема для
Схема для
В
Если файлы большие,
Так и живем!
🛠 #debug #strace
—
💬 Bashdays 📲 MAX 🌐 LF 🔵 Blog
Если открыть файл в vim, то lsof покажет этот файл открытым. А вот если открыть файл в nano, то lsof не факт, что покажет этот файл открытым. Ну видимо nano не постоянно держит открытым файл.
Давай покопаем глубже и посмотрим что происходит. Расчехляем лабу!
ㅤ
В первом терминале запускаем:
echo "secret data" > test.txt
nano test.txt
Во втором запускаем глазища:
sudo strace -e open,openat,write,close -p $(pgrep nano)
Пока пусто. Теперь в первом терминале нажимаем
CTRL+O и смотрим выхлоп во втором терминале:openat(AT_FDCWD, "test.txt", O_WRONLY|O_TRUNC) = 3
write(3, "secret data\n", 5) = 5
close(3) = 0
Получается
nano запихивает весь файл в RAM и только после манипуляций с ним производит запись на диск, то есть не держит его постоянно открытым. По этой причине lsof ничего и не показывает.Теперь идем в
vim и повторяем предыдущие команды:vim test.txt
Но во втором терминале запускаем:
watch -n 0.01 "lsof | grep test.txt"
И сразу же видим что
lsof показывает открытые файлы:vim 6423 user 5u REG 8,48 12288 11148 /tmp/.test.txt.swp
vim 6423 6424 vim user 5u REG 8,48 12288 11148 /tmp/.test.txt.swp
Но это не сам файл
test.txt, это его swap версия, то есть создается еще один файл. Если открыть такой файл, то в нем будет мусор:0000000 3062 4956 204d 2e39 0031 0000 1000 0000
0000010 bfdc 69a7 b9a1 0000 1917 0000 7375 7265
0000020 0000 0000 0000 0000 0000 0000 0000 0000
Этот файл, vim использует для crash recovery, undo history, file already open, incremental writes и т.п. Получается что vim постоянно держит открытый swap, а не исходный файл.
Если выполнить:
lsof -p 6423
То увидим всю подноготную этого процесса включая дескрипторы.
Ну и финт ушами. В первом терминале выполняем:
vim test.txt
Во втором:
mv test.txt test.old
И видим что
vim грязно выругался: E211: File "test.txt" no longer available. А если все то же самое проделать с
nano то он даже не пискнет, потому что файл загружен в память и ему похеру что мы физически снесли файл с диска. Можно снова нажать CTRL+O и он даже предложит нам его сохранить со старым именем.Вот тут уже можно почесать репу, получается
nano работает быстрее чем vim? Неа, vim тоже загружает файл в память (buffer ram). А swap файл это всего лишь журнал изменений либо undo-файлы. Swap не заменяет память, он выступает в роле дополнительного инструмента.Схема для
vim такая:disk file → RAM buffer (vim)
↓
swap file (.swp)
Схема для
nano попроще:disk file → RAM buffer
В
nano нет ни рекавери, не другой подобной хуйни-муйни. Ну а по скорости, разницы практически нет (если файлы небольшие), файлы читаются один раз, оба редактора работают в памяти, ну а linux page cache делает чтение еще быстрее.Если файлы большие,
vim все же предпочтительнее, у него более продвинутый механизм по работе с буферами.Так и живем!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
1 81