Я вот в некоторых случаях отношусь к программированию как к искусству, даже, если хотите, своего рода перфомансу и в том числе поэтому пишу скрипты - там всё достаточно наглядно может быть. Вот, скажем, использование модуля threading даже при наличии GIL в Python, может, мне кажется, с некоторой вероятностью "читателя" натолкнуть на мысль "ну хорошо, вот в жизни реализуется поток команд, а не происходит ли чего одновременно с этим в потоке данных, может стоит присмотреться к окружающей действительности повнимательнее". Или например, наследование ввода-вывода от того же threading.Thread тоже своего рода перфоманс (с изрядной долей практической пользы, конечно)? Или гибридные cmd/js скрипты: если жёсткое деление на "левую" и "правую" "стороны истории" - это "распад" (условно "ядерный"), то использование "гибридных" технологий - "синтез" и "освоение новых территорий" в "пространстве смыслов"? Вообще, ИИ также помогает визуализировать некие абстракции. Вот, например, "Соловей российский Славный Птах" Сберовским ИИ был неплохо у меня показан. Или "Поле, русское поле" тоже прекрасно визуализировано после уточнений, что поле - векторное при использовании гипотезы мультивселенных... Какой вывод: отношение к программированию как к искусству, наверно, всё же никуда не денется, но ему придётся сильно потесниться, когда существенная часть "невидимого мира" скроется в погоне за (в некоторых случаях) бездумным материализмом. Не бездумный материализм - это в том числе протоколирование событий "невидимого мира". Кто только потом расшифрует и как ("волосы дыбом встают" порой)? Вот кратко мнением по поводу применения ИИ во всём что связано с информатикой ("computer science" without computer) поделился... :)
На GitHub обновил батник "Обновить скрипты для скачивания видео.cmd" Это тоже гибридный cmd/js скрипт. Предназначен для автоматической загрузки текущих версий моих скриптов на компьютер пользователя с установленной Windows. В параметрах можно задать кодировку и выполнить некоторую замену в тексте скачиваемых скриптов. Весь текст скрипта не привожу из соображений объёма, но только cmd часть:
@set @x=0 /*
@echo off
chcp 65001 >nul
setlocal
:: Договор публичной оферты на оказание услуг технической поддержки.docx: <Удалено в соответствии с Правилами Хабра в отношении коммерческой информации>
call :update_file "Платёжная информация.html"
call :update_file "Некоторые отсоединённые GnuPG подписи/Платёжная информация.html.sig" /raw
:: Для использования yt-dlp форкните/клонируйте соответствующий репозиторий или скачайте оттуда екзешник: https://github.com/yt-dlp/yt-dlp
:: Он потом будет автоматически обновляться этим батником (при отсутствии проблем с блокированием интернета)
.\yt-dlp.exe -U
call :update_file "Обновить скрипты для скачивания видео.cmd" new
call :update_file y.cmd /coding:Windows-1251 /rep:"^(set test_prev_downloaded=)1$`$10;(^set extension=)\S+$`$1mp4"
call :update_file "Monitor2-2013/refs/heads/main/Video processing/Оглавление.js" https://raw.githubusercontent.com/kvk-2015 /coding:Windows-1251
::call :update_file Search.js
exit /b
:: Если вам будут мной предоставлены в рамках технической поддержки индивидуально настроенные под ваши потребности скрипты,
:: обновить их можно будет при помощи https://download.kde.org/stable/kdiff3/ Методику или сами найдёте, или я подскажу...
:update_file
set head=%2
set is_url=
if -%2- == -new- (set new=.new) else (set new=&if not -%2- == -- (set head=%head:~10%&set is_url=%head:*-=%))
set head=https://kvk-2015.github.io
if -%is_url%- == -2015- set head=%2
set output_file=%1
set output_file=%output_file:*и/=%
set output_file=%output_file:*g/=%
set output_file=%output_file:"=%%new%
del /f "%output_file%.bak" 2>nul
rename ".\%output_file%" "%output_file%.bak" 2>nul
set page=%1
setlocal enabledelayedexpansion
set page=!page: =%%20!
setlocal disabledelayedexpansion
set page=%page:"=%
curl.exe --output ".\%output_file%" %head%/%page%
if not defined new cscript /nologo /e:javascript "%~dpnx0" ".\%output_file%" %2 %3 %4 %5 %6 %7 %8 %9
goto:eof */
// Для скачанного скрипта можно выполнить патчинг согласно вашим предпочтениям
<Далее .js часть скрипта, не приводится из-за ограничений объёма поста на Хабре>Ручная смена кодировки скрипта, если вдруг кому захочется, подразумевает некоторые изменения в коде (другие мои скрипты таких "сложностей" не предполагают - их можно просто сохранить в нужной кодировке). Можно получить объяснение работы всей этой подсистемы у Алисы Про, конечно, только весьма ограниченно доверяя им. Скрипт Search.js имеет несколько ограниченное применение, поэтому не предлагается для скачивания по умолчанию, в нём выполняется поверка не просматривали ли уже видео, скачанное недавно при помощи yt-dlp (имена файлов, из которых для целей поиска выделяется только id, передаются в него в виде параметров командной строки). Предполагается, что просмотренные видео удаляются вручную из истории файлов Windows 10 из-за сбоев, в то же время информация о них продолжает присутствовать в базе данных. Если в скрипте установлено, что contains_only = true, просто проверяется наличие указанного id в базе, а не выполняется сравнение отдалённости групп случаев по оси времени условно.
На GitHub сегодня обновил батник для скачивания видео через yt-dlp. Текущую версию попытался продублировать здесь:
@set @x=0 /*
@echo off
chcp 65001 >nul
setlocal
set VideoURL=gaRy9U0yiSA
set head=
set suffix=
set series=%%(series)s.
call :set_template
set format=b
set enable_format_recommendations=1
set extension=mov
set AppPath=D:\kvk\Utilities\GitHub\yt-dlp\yt-dlp.cmd
if not exist %AppPath% set AppPath=yt-dlp.exe
if not -%1- == -- (set format=%1 & set enable_format_recommendations=0)
set tempFileName=%random%.tmp
call %AppPath% -o "%%template:.!=%%" --windows-filenames --socket-timeout 45 --print-to-file filename %%tempFileName%% --skip-download %%VideoURL%%
if not errorlevel 0 if exist %tempFileName% del /q %tempFileName%
if not exist %tempFileName% exit /b
cscript /nologo /e:javascript "%~dpnx0" %tempFileName%
set /p filename=<%tempFileName%
set processed_series=%filename:!.=!%
if not "%processed_series%" == "%filename%" (setlocal enabledelayedexpansion & set series=!series:~0,-2! & setlocal disabledelayedexpansion & call :set_template & set filename=%processed_series%)
set filename_without_series=%filename:NA. =%
if not "%filename_without_series%" == "%filename%" (set series=& call :set_template & set filename=%filename_without_series%)
setlocal enabledelayedexpansion
set filename=!filename:.mp4=.%extension%!
set filename=!filename:.webm=.%extension%!.txt
setlocal disabledelayedexpansion
echo %VideoURL% > "%filename%" && del /q %tempFileName%
cscript /nologo /e:javascript "%~dpnx0" "%filename%"
echo.>> "%filename%"
call :size "%filename%"
set tempsize=%filesize%
call %AppPath% --socket-timeout 45 --print formats_table %%VideoURL%% >> "%filename%"
if not errorlevel 0 exit /b
call :size "%filename%"
if %tempsize% == %filesize% exit /b
for /f %%i in ('cscript /nologo /e:javascript "%~dpnx0" "%filename%" /FORMATRECOMMENDATIONS:%enable_format_recommendations%') do if defined enable_format_recommendations if "%enable_format_recommendations%" == "1" if not "%%i" == "" set format=%%i
if -%1- == ---- exit /b
start "yt-dlp: %VideoURL%" %AppPath% -o "%template%" --split-chapters --postprocessor-args "SplitChapters+ffmpeg:-map_metadata -1" --video-multistreams --audio-multistreams --windows-filenames --remux-video %extension% --concurrent-fragments 10 --socket-timeout 45 --abort-on-unavailable-fragment --exec "pause " --embed-metadata --format %format% %VideoURL% ^&exit/b
:set_template
set template=%head%%series%%%(title)s [%%(id)s]%suffix%.%%(ext)s
exit /b
:size
set filesize=%~z1
goto:eof */
var fso = new ActiveXObject("Scripting.FileSystemObject"), fName = "", newText = "";
if(WSH.Arguments.Unnamed.Count && fso.FileExists(fName=WSH.Arguments.Unnamed(0))){
with(new ActiveXObject("ADODB.Stream")){Type=2; Mode=3; Open(); Charset="UTF-8"; LoadFromFile(fName);
Position=0; var newText=ReadText().replace(/\s*$/, ""); Close();
newText = ((isTemp=/^\d+\.tmp$/.test(fName)) ? newText.replace(/\(/g, "{").replace(/\)/g, "}") : newText.replace(/\r\n|\n/g, "\r\n"));
fso.DeleteFile(fName);
Open(); Charset="UTF-8"; Position=0; WriteText(newText + (isTemp ? "" : "\r\n")); SaveToFile(fName); Close();
}
}
if(1*WSH.Arguments.Named.Item("FORMATRECOMMENDATIONS") && newText){
var line, lines = newText.split("\r\n"), recommended_audio_format = "", recommended_video_format = "";
for(var lineIndex in lines){
if(/audio only/.test(line=lines[lineIndex])){
if(/(^hls\S+)\s.+audio only.*$/.test(line))recommended_audio_format = RegExp.$1;
else if(!/^hls/.test(recommended_audio_format) && /(^\S+)\s+m4a/.test(line))recommended_audio_format = RegExp.$1;
} else if(/video only/.test(line)){
if(/(^hls\S+)\s.+video only.*$/.test(line))recommended_video_format = RegExp.$1;
else if(!/^hls/.test(recommended_video_format) && /(^\S+)\s+mp4\s+1920x1080\s+.*avc1/.test(line))recommended_video_format = RegExp.$1;
}
}
WSH.echo(recommended_audio_format && recommended_video_format ? recommended_audio_format + "+" + recommended_video_format : "");
}По поводу ИИ некоторые размышления. Раньше всё ПО было документировано и самодокументировано. Совсем раньше можно было всю документацию по продукту держать в голове целиком. Потом доступ стал только по поиску и люди стали знать продукты фрагментарно, значит требовались уже коммуникации на уровне пользователей/экспертов. С развитием ИИ, насколько понимаю, документирование вообще пропало напрочь. Неизвестно что продукт может, не известно в каких областях он достоверен, вообще ничего не известно, похоже. И чего делать? С кем советоваться? Кто-то подскажет без ущерба для себя и других? Проблема?..
В честь "Всемирного дня бэкапа" решил частично проверить восстановление той части резервного копирования, что описана у меня сколько-нибудь подробно здесь (на Дзене, в той же статье короткие воспоминания о бэкапах в 80-е годы). Скрипты копирования такие:
@start "split into BD-RE slices" %comspec% /k py .\bd_split.py %~nx1#! python3.13
import sys
BUF_SIZE = 1024 * 1024
FS_SIZE = 2048 * 512 # кратно BUF_SIZE, значит можно использовать сравнение count == BD_DISK_SIZE
BD_DISK_SIZE = 25025314816 - FS_SIZE
file_name = sys.argv[1]
source = r"K:\backup\2311\{0}".format(file_name)
dest_head = r"D:\kvk\YandexDisk\Acronis\{0}".format(file_name)
with open(source, "rb") as input:
part = 1
while True:
count = 0
with open(dest_head + ".{0:02d}".format(part), "wb") as output:
bytestring = input.read(BUF_SIZE)
while bytestring:
count += output.write(bytestring)
if count == BD_DISK_SIZE:
part += 1
break
elif count > BD_DISK_SIZE:
raise Exception("Превышен максимальный размер диска для части {0}...".format(part))
bytestring = input.read(BUF_SIZE)
else:
break
Поскольку облако не специализированное, подписываю GnuPG подписью получившиеся кусочки для последующего возможного контроля целостности.
Сегодня в процессе проверки подключил внешний жёсткий диск с бэкапами, для самой маленькой резервной копии из недавних посчитал SHA256, восстановил её же из облака вместе с подписями, проверил их, собрал эту инкрементную резервную копию из кусочков, проверил SHA256. Совпали. Последний раз проверял по такой схеме наверно более 10 лет назад, ну и сегодня "на всякий случай" :)
А вообще у меня бэкапы проверяются периодически (какие автоматически после каждого резервного копирования, какие вручную еженедельно), а восстановление из копии при изменениях в "железе" и обновлении софта обычно.
Так совпало, что прочитал сегодня на Хабре о том, что люди, по мнению Google, могут обмениваться своими наработками и подходами к медицине (мнение высказал у себя в сообществе ВКонтакте), также статью о том, что сисадмины не любят делиться своими скриптами по типу "набросал за пару минут, использую и ни с кем не делюсь - там всё просто и каждый то же самое без проблем может сделать", а также сегодня же скриптик написал для подготовки к печати данных по давлению и пульсу из Samsung Health и решил поделиться здесь вполне рабочим решением. Сначала вручную фиксируем давление и пульс в Samsung Health при каждом измерении тонометром (данные по пульсу с фитнес браслета у меня фиксируются автоматически, можно потом обрабатывать так же). Когда нужно, экспортирую в html данные за последние 2 недели, месяц, два или три месяца (для пульса делал ещё сортировку для кардиолога {у меня брадикардия была}). Потом отправляю файл на комп (через поделиться, Samsung с Microsoft здесь дружат) и перетаскиваю полученный файл (данные с давлением и пульсом) на предложенный скрипт ("Для печати кардиологу.js"), или в качестве первого неименованного параметра при запуске указываю путь к полученному файлу (перетаскивание файла/файлов на скрипт {CMD/JS/VBS} в Windows просто передаёт полные пути в качестве аргументов в этот скрипт). Замечу ещё, что у меня в качестве кодировки скриптов на Windows 10 установлена utf-8, для других вариантов параметр -2 вызываемого метода fso не проверял.
var fso=new ActiveXObject("Scripting.FileSystemObject");
var a = WSH.Arguments; if(a.length){
s = fso.OpenTextFile(fn=(a.UnNamed.Item(0)), 1, false, -2).ReadAll();
s = s.replace(/(table.tableWithBorder.*font-size:)41px/, "$125px")
.replace(/ style="min-width:\d+px"/gi, "")
.replace(/ style="height:113px"/i, "")
.replace(/ style="height:75px"/gi, "")
.replace(/(id="tableTitleDiv".*Заметки)/i, "$1");
s = s.replace(RegExp.$1, RegExp.$1.replace(/width:\d+px;/gi, ""));
fso.OpenTextFile(fn.replace(/[_.](html)$/, " (вариант для печати).$1"), 2, true, -2).Write(s);
}

Не говорю, что скрипт идеален, но JS (WSH) был для меня довольно долгое время основным рабочим инструментом, поэтому пользуюсь по старой памяти без особого напряга. Скрипт меняет размер шрифта и таблицу, чтобы она помещалась по ширине на книжную страничку A4.
На днях опубликовал на GitHub свой скрипт 2013 года, который наполнял с ИБП Ippon Smart Winner 750 базу данных IBM DB2 данными по напряжению сети (за каждую секунду в течение года, по результатам наблюдений скорректировал уставки на реле напряжения, их безопасность для техники подтвердилась при отгорании нуля), обновлял статус моего DynDNS клиента по данным с роутера, запускал и останавливал виртуальную машину VMware Player (там у меня крутилась openSUSE с сайтом на Apache/Django) по расписанию и когда в планировщике BeholdTV была запланирована запись кабельного телевидения (это было необходимо, поскольку видео захватывалось в .asf/x264 - crf18/AC3 без использования графического ускорения и на всё ресурсов не хватало), следил за качеством ADSL линии. А сегодня дополнил ещё рядом скриптов: в 2014 перенёс сайт на Raspberri Pi (Arch Linux ARM) и там стал захватывать IPTV видео. Про захват у меня на Дзене можно почитать, а скрипы создания оглавления и некоторого контроля версии файлов (WSH/JS) опубликовал на GitHub здесь же. Также скрипты по установке времени и некоторой оптимизации скорости отклика сайта, мониторинга доступности посредством Online Domain Tools. Ещё дополнил своими Windows скриптами по работе с СУБД IBM DB2 Express-C и её оптимизации по книге "Best practices Tuning and monitoring database system performance" (она тоже выложена в соответствии с лицензией). Изначально не включил библиотеку RGraph для построения графиков, теперь выложил под лицензией MIT 2013 года.
На днях вышел из строя ИБП. Переключился на стабилизатор. Было уже. До техники APC стоял ИБП Ippon Smart Winner 750. Мониторил напряжение. Сохранял в базе данных SQL сервера IBM DB2 Express-C 10.5 данные за каждую секунду и хранил в течение года. Это помогло выставить уставки на реле напряжения и нормально пережить несколько отгораний нуля без потерь для техники. Скрипты соответствующие опубликовал сегодня на GitHub у себя. При работе от стабилизатора приходилось потом чинить неоднократно SQL базу данных, благо у меня было настроено журналирование в "Архивном" режиме, а сама база данных периодически тестировалась на наличие повреждений. Сложнее с остальной частью данных на компьютере: в NTFS принято частичное журналирование и внезапное отключение ведёт к необходимости решать, восстанавливать ли из бэкапа или соглашаться с тем, что возможно какие-то повреждения будут не сразу обнаружены и могут вызвать проблемы с дальнейшим ремонтом. Чуть раньше такой же пост на Дзене у себя опубликовал.
Информация
- В рейтинге
- 2 339-й
- Откуда
- Кушва, Свердловская обл., Россия
- Дата рождения
- Зарегистрирован
- Активность