четверг, 26 ноября 2020 г.

Linux: не осталось свободного места на диске

Интересная проблема обнаружилась. Предположим, есть жесткий диск с файловой системой ext4 на борту, забитый почти под завязку всяким файловым барахлом. Если с ним работать под рутом, то всё хорошо: можно файлы создавать/писать/читать/удалять. Если же это пропробовать делать с правами непривилегированного пользователя, то получим ошибку: на диске не осталось свободного места. Команда df -H тоже показывает, что 0% доступно для непривилегированной учетной записи и 2% для привилегированной.

Оказывается, линукс резервирует на диске 5% для суперпользователя - чтобы даже в случае нехватки свободного места всякие системные процессы продолжали работать, писать журналы, вести дневники и т.п. Поскольку в данном случае такое резервирование не требуется, можно эту величину поправить командой:
sudo tune2fs -m 0 /dev/sdc1

Литература:

https://superuser.com/questions/444269/display-filesystems-free-space-available-to-the-root-user

четверг, 10 сентября 2020 г.

Linux+Windows: Доступ из MS Windows к оконным приложениям X Windows

Захотелось поработать удалённо с оконными приложениями линукса. Насколько я знаю, линукс позволяет такие штуки - когда программа выполняется на одной машине, а окна рисует на другой - поэтому надеялся обойтись без средств удаленного доступа типа TeamViewer или VNC, и эта надежда отчасти оправдалась. Нужна лишь небольшая настройка.

1. Настраиваем линукс, на котором будут выполняться программы. У меня Slackware, но, думаю, под другими вариантами настройка будет примерно такой же. Нужно в конфигурационном файле /etc/ssh/sshd_config найти и раскомментировать следующие строки:

X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes

2. Настраиваем Windows, которая будет заниматься отрисовкой окон. Оконные приложения в X11, как я понял, устроены хитро: приложение является клиентом, а окнами занимается сервер, которому, в принципе, всё равно где работать - на этой же машине или на соседней. Поэтому нужно поднять сервер X11. Мой выбор пал на Cygwin/X.

2.1. Устанавливаем Cygwin/X. Это несложный процесс: запускаем установщик cygwin, в которм выбираем для установки пакеты:

xorg-server
xinit
xorg-docs
xlaunch

2.2. Настраиваем Cygwin/X. Как выяснилось, "из коробки" у него не очень хорошо с подключениями tcp, переключением раскладки клавиатуры и глубиной цвета в rdp-сессии.

2.2.1. Переключение раскладки клавиатуры: в папке путь_установки_cygwin/home/имя_пользователя/ создаём файл .XWinrc с таким содержимым:

XKBLayout   us,ru
XKBModel    evdev
XKBOptions  grp:alt_shift_toggle
XKBRules    base
XKBVariant  ,winkeys 

Клавиатура будет переключаться по Alt+Shift. Если хотим Ctr+Shift, надо в XKBOptions указать grp:ctrl_shift_toggle.

2.2.2. Доступ по tcp: изменяем ярлык запуска сервера, дописывая в него параметр -listen tcp после двойного минуса (перед двойным минусом перечисляются параметры, относящиеся к клиенту, после него - к серверу):

путь_установки_cygwin\bin\run.exe --quote /usr/bin/bash.exe -l -c "cd; exec /usr/bin/startxwin -- -listen tcp"

Сервер будет ожидать входящие подключения на 6000 порту.

2.2.3. Корректировка глубины цвета: если работа с Windows производится в RDP-сессии, как у меня, то окна отрисовываются почему-то с минимальной глубиной цвета, чуть ли не в 16-цветной палитре. Исправляет это параметр -nocompositewm. То есть, окончательно команда ярлыка запуска сервера приобретает следующий вид:

путь_установки_cygwin\bin\run.exe --quote /usr/bin/bash.exe -l -c "cd; exec /usr/bin/startxwin -- -listen tcp -nocompositewm"

2.3. Настраиваем PuTTY. Переходим в категорию Connection -> SSH -> X11 и выставляем там параметры:

Enable X11 Forwarding              -> true
X11 Location                       -> :0.0
Remote X11 authentication protocol -> MIT-Magic-Cookie-1
X authority file for local display -> путь_установки_cygwin\cygwin\home\имя_пользователя\.Xauthority

После всех настроек можно заходить через PuTTY на линуксовую машину и запускать на ней оконные приложения (xclock, xlogo, firefox и т.д.). Работает всё, правда, небыстро, но тут уж - как есть...

Литература:

http://tolik-punkoff.com/2016/11/21/nastrojka-x11-forwarding-cherez-ssh-s-pomoshhyu-putty-i-xming/

https://datacadamia.com/ssh/x11/cygwinx_remote_client#with_putty

https://stackoverflow.com/questions/34932495/forward-x11-failed-network-error-connection-refused

https://x.cygwin.com/docs/ug/setup.html#setup-cygwin-x-installing

http://cygwin.1069669.n5.nabble.com/X-colormap-problem-when-viewed-via-Microsoft-Remote-Desktop-td132076.html

понедельник, 25 мая 2020 г.

Linux: заменить в файле байты со значением 0x56 на байт со значением 0x65

Задача: поменять в файле file.bin у всех байтов равных, скажем, 0x56 значение на 0x65.

Решение:
xxd -p < file.bin | fold -w2 | sed 's/56/65/g' | xxd -p -r > patched_file.bin

По порядку:

xxd -p < file.bin - печатает содержимое файла file.bin в текстовом виде: "1256340021..."

fold -w2 - разбивает входную строку на строки по два символа:
12
56
34
00
21
...

sed 's/56/65/g' - меняет 56 на 65

xxd -p -r > patched_file.bin - восстанавливает байты обратно из их значений в текстовом виде

Литература:
https://www.commandlinefu.com/commands/view/194/binary-searchreplace

среда, 20 мая 2020 г.

Debian: python-скрипт, sql server 2005 и настройки openssl

Оказывается, если при переезде на новое место жительства скрипт, написанный в незапамятные времена на питоне и общающийся с Sql Server 2005 через pyodbc+unixODBC+msodbcsql (вот такое вот извращение), стал жаловаться примерно так: [ODBC Driver 17 for SQL Server]SSL Provider: [error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol], то можно поправить настройки ssl в файле /etc/ssl/openssl.cnf:
[system_default_sect]
MinProtocol = TLSv1.0
CipherString = DEFAULT@SECLEVEL=1

вторник, 14 апреля 2020 г.

Oracle + PL/SQL - поиск строки в базе

Возникла тут одна небольшая задачка. Есть некая строка, например "ABC123", есть база данных на Oracle, и нужно опеределить, в каких таблицах и каких столбцах эта строка встречается. Известен владелец таблиц, назовём его HUHMUH. В общем, требуется некий reverse engineering.

К сожалению, я с ораклом дел практически не имел, поэтому не знаю всех его возможностей. Не исключено, что есть какой-нибудь штатный способ для решения этой задачи. Мне же не пришло в голову ничего умнее, чем перебрать все таблицы и все столбцы по очереди и поискать селектами строку в них.

Поскольку всё происходит под линуксом в командной строке, возникла мысль воспользоваться инструментом SQL*Plus, входящим в комплект Oracle Instant Client-а (у меня он версии 12.2). Запуск скрипта, хранящегося в файле myscript.txt, с помощью этой утилиты не представляет сложностей:
#!/bin/sh

export NLS_LANG=American_America.AL32UTF8

ora_path=/opt/oracle/instantclient_12_2

exit | $ora_path/sqlplus -S mylogin/mypassword@myserver:1521/mydatabase @myscript.txt > output.txt
Запускаем, получаем в файле output.txt всё, что этот самый скрипт посчитает нужным сообщить.

Сам скрипт тоже не содержит ничего необычного. Выглядит он так:
-- без этого не работает dbms_output
SET SERVEROUTPUT ON

-- без этого пишется лишняя строка "PL/SQL procedure successfully completed"
SET FEED OFF

DECLARE
    search_string  varchar(256);

    row_count integer;

    CURSOR cur
    IS
    SELECT
        owner,
        table_name,
        column_name
    FROM
        all_tab_columns
    WHERE
        owner = 'HUHMUH'
        and data_type like '%CHAR%'
    ORDER BY
        1, 2;

BEGIN

search_string := 'ABC123';

-- можно было сразу FOR r IN (SELECT ...) LOOP ... END LOOP;
FOR r IN cur
LOOP
    BEGIN

        EXECUTE IMMEDIATE 'SELECT count(*) FROM '
            || r.table_name
            || ' WHERE '
            || r.column_name || ' = ''' || search_string || ''' '
            INTO row_count;

        IF row_count > 0 THEN
            dbms_output.put_line(r.owner || '.' || r.table_name || ' -> ' || r.column_name);
        END IF;

    EXCEPTION
        WHEN OTHERS THEN
            dbms_output.put_line('error ' || r.owner || '.' ||r.table_name || ' -> ' || r.column_name);
            CONTINUE;
    END;

END LOOP;

END;

-- без этого не возвращается результат dbms_output
/

Вот, собственно, и всё. Работает долго, но нужные мне данные нашло.

среда, 4 марта 2020 г.

Машина Тьюринга

Почему-то никак не удавалось найти какую-нибудь машину Тьюринга, для которой можно было бы удобно составлять программы. Пришлось набросать самому:
Машина Тьюринга

С полубесконечной лентой. Всё по канону - каретка считывает символ, берёт своё текущее состояние и на основе этой пары делает работу: пишет новый символ, меняет своё состояние и сдвигается влево/вправо или остаётся на месте. Для решения учебных задачек - типа, "заменить в строке все символы b на c" - вполне подходит.

Пусть лежит для коллекции.
Если что, там же болтаются худо-бедно работающие эмуляторы нормального алгоритма Маркова и машины с неограниченными регистрами.

среда, 19 февраля 2020 г.

Windows 10: где хранятся ссылки на обои

Если использовали в качестве обоев рабочего стола какую-то не ту картинку, она ещё долго будет о себе напоминать, болтаясь в списке доступных вариантов выбора. Чтобы её оттуда удалить, надо залезть в реестр:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers
и удалить параметр, содержащий путь к ненужной картинке.

Литература:
https://www.howtogeek.com/370417/how-to-clear-recently-used-desktop-background-images-from-windows-10-settings/

вторник, 18 февраля 2020 г.

RDP: общий буфер обмена

При подключении по RDP на одной машине перестал работать в сессии общий буфер обмена. Оказалось, за эту полезную функцию отвечает процесс rdpclip.exe. Перезапустил (прибил в диспетчере задач и из диспетчера же задач запустил), общий буфер обмена восстановился.

Литература:
https://1cloud.ru/help/windows/rdp-sessija_problemy_s_buferom_obmena

понедельник, 17 февраля 2020 г.

InstallShield - ошибка 1720

При разворачивании msi-пакета на очередной машине под управлением Windows 7 обнаружилась проблема: в самом начале установки пакет выдаёт ошибку "1720 Ошибка пакета установщика Windows. Сценарий, требующуюся для завершения установки не может быть выполнен. Обратитесь к системному инженеру или к поставщику пакета", и установка прекращается.

Попробовал запустить установку с журналированием. Делается это, напомню, командой:
msiexec /i пакет.msi /L*V журнал.log

В файле журнал.log в результате оказывается много всего, но сориентироваться, с какого момента всё пошло не так, можно. В моём случае это оказалась некая CustomAction. Имя этой CustomAction из журнала выудить можно, а что именно она делает - загадка.

Однако, оказалось, всё не так плохо. Есть специальный просмотрщик/редактор инсталляционных пакетов, Orca.exe, входящий в состав Windows SDK, который позволяет посмотреть эти самые CustomAction-ы.

В моём случае это оказалась проверка на наличие .NET 4. Проверка представляет собой VB-скрипт, который, будучи вытащен в отдельный vbs-файл, запускается без проблем, а вот в русле инсталляции работать отказывается. Скрипт этот выглядит так:
NetFrameworkTargetVersion = GetRegistryKey("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\TargetVersion", "0.0.0")
if NetFrameworkTargetVersion = "0.0.0" or NetFrameworkTargetVersion <> "4.0.0" then
  NetFrameworkUrl = "http://www.microsoft.com/ru-ru/download/details.aspx?id=17718"  
  InfoMsg = "Для корректной работы требуется Microsoft .Net Framework 4 или более старшая версия"
  InfoMsg = InfoMsg + "Ссылка для скачивания представлена ниже"
  InputBox InfoMsg, "Программа - Установка", NetFrameworkUrl
  Err.Clear
  Err.Raise 100
end if

function GetRegistryKey(RegistryKey, DefaultValue)
  Dim WSHShell, value
  On Error Resume Next
  Set WSHShell = CreateObject("WScript.Shell")
  Value = WSHShell.RegRead(RegistryKey)
  if Err.number <> 0 then
    GetRegistryKey = DefaultValue
  else
    GetRegistryKey = Value
  end if
  Set WSHShell = Nothing
end function
Почему он так себя ведёт, так и осталось загадкой. В сети, правда, есть слухи, что из соображений безопасности вызов WScript.Shell не приветствуется в CustomAction-ах.

Однако, пакет-то развернуть надо. Пришлось в инталляционном пакете при помощи всё той же Orca.exe удалить все CustomAction-ы, содержащие проверки такого рода, и тогда инсталляция прошла нормально.

P.S. Там правда, есть ещё одна тонкость. Если программа была установлена раньше, а теперь не даёт себя изменить/удалить из-за вышеописанной проблемы, то патч msi-пакета ничего не даст: дело в том, что копия установочного пакета сохранена в папке C:\Windows\Installer (имя копии можно узнать из вышеупомянутого файла журнал.log). Поэтому при запуске пакета будет запущена его сохраненная копия. Если же перед запуском прибить эту самую копию, тогда пропатченный пакет отработает нормально.