Lazarus, сортировка TStringList.

Преамбула

Иногда список строк (TStringList) требуется сортировать, что, как бы, понятно. Но во Freepascal сортировка устроена довольно странно, в C# у аналогичного класса из коробки несколько больше возможностей, во всяком случае, можно поменять направление, по возрастанию или по убыванию. С хитрыми сортировками, конечно, тоже вылезает нетривиальщина, но на то они и хитрые сортировки.

Тестовые списки

Для начала сформируем тестовые списки, для русского и английского языков. Там код тривиален, потому не буду загружать заметку, ссылки на PasteBin:

Тестовый список для английского языка
Тестовый список для русского языка

Заодно уж и выведем списки в их изначальном виде:

Стандартная сортировка

Она же единственная из коробки, является стандартной сортировкой по возрастанию, т.е. список сортируется от меньшего к большему, а об алгоритме будет ниже. Вызов функции простой:

lstTest.Sort;

Пробуем. Выводим список на экран:

WriteLn('Сортировка по возрастанию (по-умолчанию, логическая):');
i:=0;
while i < lstTest.Count do begin
WriteLn(lstTest[i]);
inc(i);
end;

Writeln(); WriteLn('Press Enter...'); ReadLn();

Результат:


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

Стандартный алгоритм сравнения строк во freepascal

Алгоритм:

1. Строки сравниваются посимвольно. Например, в словах parrot и puppy первые символы (p и p) равны, а далее a меньше u, т.е u в кодовой таблице находится ниже, чем a.
2. На этом сравнение прекращается, строка puppy больше чем parrot.
3. Если начальные символы строк совпадают, то в дело вступает длина, чем строка длиннее, тем она больше, поэтому, зависимая от центра Каталония, все еще больше, чем кот, который гуляет сам по себе:

program test;
var
  S1:string;
  S2:string;

begin
  S1:='cat';
  S2:='catalonia';
  if S1 < S2 then Writeln ('S1 (',S1,') < S2 (',S2,')' );
  if S1 = S2 then Writeln ('S1 (',S1,') = S2 (',S2,')' );
  if S1 > S2 then Writeln ('S1 (',S1,') > S2 (',S2,')' );
  Readln();
end.

Вывод:

S1 (cat) < S2 (catalonia)

Что, конечно, печально, потому что кот свободнее Каталонии, и явно больше в этом смысле.

Пользовательские функции сортировки

Ограничение, накладываемое одной функцией сортировки в комплекте класса TStringList легко решается тем, что можно подключить любую пользовательскую сортировку ссылкой на внешнюю функцию.

Для этого надо установить пользовательскую функцию сортировки, таким вот образом:

lstTest.CustomSort(@MySort);

где MySort — имя вашей функции сортировки. Естественно, она должна быть заранее создана, чтобы все откомпилировалось и заработало.

Не забудьте про символ @ перед именем функции, в Delphi не надо было его указывать, компилятор сам знал, где вместо имени функции вставить ссылку на ее адрес, в freepascal это надо указывать явно.

Формат функции следующий:

MySort(List: TStringList; Index1, Index2: Integer): Integer;

Т.е. на входе нужна переменная типа TStringList и две переменные типа Integer, для индексов строк в списке, функция должна возвращать значение типа Integer:

1 — Если строка Index1 > Index2
0 — Если строки равны
-1 — Если строка Index1 < Index2

Конечно, по мнению пользовательского алгоритма сортировки. Например, можем повторить стандартный метод сортировки:

function SortByAsc(List: TStringList; Index1, Index2: Integer): Integer;
begin
  if List[Index1]>List[Index2] then
  begin
    Result := 1;
    Exit;
  end;
  if List[Index1]=List[Index2]
    then Result := 0
    else Result := -1;
end;

Внезапно, починился русский язкы 🙂

Сортировка по убыванию

function SortByDesc(List: TStringList; Index1, Index2: Integer): Integer;
  begin
    if List[Index1]<List[Index2] then
    begin
      Result := 1;
      Exit;
    end;
    if List[Index1]=List[Index2]
      then Result := 0
      else Result := -1;
  end;

Вообще просто, достаточно заменить знак > на < в операторе сравнения.

Другие пользовательские сортировки

Возможности пользовательских сортировок не ограничены практически ничем. Покажу, как обычно, самое простое — сортировка строк по длине.

Сортировка по возрастанию:

function SortByLenAsc(List: TStringList; Index1, Index2: Integer): Integer;
begin
  if Length(List[Index1])>Length(List[Index2]) then
  begin
    Result := 1;
    Exit;
  end;
  if Length(List[Index1])=Length(List[Index2])
    then Result := 0
    else Result := -1;
end;

Т.е. просто применяем функцию Length в операторе сравнения:

Length(List[Index1])

Тот же вариант, но по убыванию:

function SortByLenDesc(List: TStringList; Index1, Index2: Integer): Integer;
begin
  if Length(List[Index1])<Length(List[Index2]) then
  begin
    Result := 1;
    Exit;
  end;
  if Length(List[Index1])=Length(List[Index2])
    then Result := 0
    else Result := -1;
end;

Тестовые программы

Пример для английского языка на GitHub
Пример для русского языка на GitHub

По мотивам

Обсуждения на Исходниках, но более подробнее и лучше у меня.

Lazarus. Поддержка Unicode в консоли Windows.

Продолжаем бодаться с русским языком в консоли (копия).

Ну не может же быть так, что виндовая консоль и Unicode (UTF-8) не поддерживает, подумал я. У меня и функции, которые, собственно, в программе нужны, UTF8 требуют, и с русским языком, если исходник не в UTF-8 работают криво, и в документации по Lazarus написано, что он поддерживает вывод на консоль в UTF-8, и в документации по винде написано, что она тоже нежно любит UTF-8, хотя может и в OEM(которая CP866).

Хинт оказался небольшим, неочевидным, и вообще был обнаружен чисто случайно, кодировку исходника надо поменять на на CP866, как я делал по ссылке выше, а на UTF-8 с BOM!

И нигде в документации (не в виндовой, не в Лазарувской) об этом не сказано, ну или закопано в такие бездны Варпа, что не докопался.

До (исходник в UTF-8):

После (исходник в UTF-8 с BOM):

program Project1;

begin
  WrileLn('Какая-то фигня с русскими буквами');
  WrileLn('А, уже не фигня');
  Readln();
end.

Lazarus, встроенный парсер командной строки.

Преамбула

В Lazarus есть довольно неплохой парсер командной строки, который (почти) работает из коробки.

Для его использования нужно создать приложение на базе класса TCustomApplication, который обладает таким функционалом. Готовый шаблон проекта имеется в комплекте. Проект —> Создать проект… и в появившемся окне выбрать тип проекта Консольное приложение:

Можно ввести параметры для генерации кода:

Основной код приложения размещается в процедуре DoRun, например, в procedure TMyApplication.DoRun;

Решил расширить пример с поиском файла по маске (копия), заодно поэкспериментировать с парсером командной строки.

Параметры будут такие:

Использование: smallfinder.exe <аргументы>
-h - эта помощь
-m <маска> - маска файла для поиска. Обязательный параметр
-d <директория> - Начальняя директория, если параметр не указан, используется текущая.
-s - включить в поиск подкаталоги

Анализ параметров командной строки

Примечание: весь код в процедуре TSmallfinder.DoRun.

Почему-то способ проверки из документации, случая, когда параметров нет вообще, у меня сработал криво, так что пришлось вспоминать более старый:

// check if no parameters - способ из документации нихуя не сработал

if ParamCount=0 then begin
	WriteHelp;
	Terminate;
	Exit;
end;

Но далее все вроде бы пошло как надо, единственное, что параметры регистрозависимые (т.е. -d и -D программа воспринимает как разные параметры), пока не стал с этим разбираться, может после, если сильно надо будет. Длинные имена параметров не использовал, только короткие.

Вывод помощи:

//help
if HasOption('h', '') then begin
	WriteHelp;
	Terminate;
	Exit;
end;

Процедуру WriteHelp можно создать при создании нового проекта, а потом только запомнить, примерно так:

procedure TSmallfinder.WriteHelp;
begin
  writeln('Usage: ',ExtractFileName(ExeName), ' <arguments>');
  WriteLn('-h - this help');
  WriteLn('-m <mask> - file mask for search. Parameter must be!');
  WriteLn('-d <directory> - start directory. If not, use current dir.');
  WriteLn('-s - include subdirs');
end;

Маска файла:

//mask
if HasOption('m','') then begin
	Mask:=GetOptionValue('m','');
	if Mask = '' then begin
		WriteHelp;
		Terminate;
		Exit;
	end;
end;

Стартовый каталог:

//start directory
StartDir:=GetOptionValue('d','');
if StartDir='' then begin
	StartDir:=GetCurrentDir();
end;

Искать в подкаталогах:

//Include subdirs
IncludeSubdirs:=HasOption('s','');

Ну и сам процесс поиска, до кучи:

WriteLn('Start directory: ',StartDir);
lstFiles := TStringList.Create;
FindAllFiles(lstFiles, StartDir, Mask, IncludeSubdirs);
i:=0;
while i < lstFiles.Count do begin
	WriteLn(lstFiles[i]);
	inc(i);
end;
lstFiles.Free();

Естественно, все нужные переменные перечисляем в секции var процедуры TSmallfinder.DoRun

var
   Mask, StartDir:string;
   IncludeSubdirs:boolean;
   i:LongInt;
   lstFiles:TStringList;

Примеры работы

smallfinder.exe -m *.exe -d C:\Windows

smallfinder.exe -m *.exe -d C:\Windows -s

smallfinder.exe -m *.exe

Ссылки

Мануал по обработке параметров командной строки
Пример целиком на GitHub

Lazarus: Транслит строки (в консоли)

1. Понадобятся модули regexpr и fgl:

uses regexpr, fgl;

regexpr нужен для небольшой оптимизации, a fgl — для создания аналога словаря (Dictionary).

2. Создаем тип для будущего словаря:

type
  TDictTrans=class(specialize TFPGMap<string, string>);

Документация по TFPGMap

3. Сделаем функцию для транслитерации, с одним параметром, входной строкой с русскими буквами:

function Translit(Str:string):string;
//тут будет код
end;

4. Заводим внутренние переменные функции:

var Regex:TRegExpr;
Dict:TDictTrans;
Ch,oStr,oTrans:string;
I:LongInt;

Regex — экземпляр класса для работы с регулярным выражением.
Dict — словарь для транслитерации.
Ch — транслитерируемый символ
oStr — выходная строка
oTrans — сюда будем возвращать результат транслита отдельного символа.
I — счетчик цикла, в котором будем анализировать строку.

Небольшая оптимизация

Создаем новое регулярное выражение для кириллицы (и пробела) и проверяем входную строку на наличие русских букв. Если их нет — возвращаем исходную строку и выходим из функции:

Regex:=TRegExpr.Create;
Regex.Expression:='[А-Я]|[а-я]|\s';
if not Regex.Exec(Str) then begin
   exit(Str);
end;

5. Заполняем словарь (транслит взят из старого армейского учебника времен СССР, можете сделать свой):

Dict:=TDictTrans.Create;
Dict.Add(' ','_');
Dict.Add('А','A'); Dict.Add('а','a');
...
Dict.Add('Я','JA'); Dict.Add('я','ja');

Словарь целиком на PasteBin

6. Инициализируем переменные, используемые в цикле:

Ch:=''; oStr:='';

7. Заводим цикл for, нумерация символов в строке идет с 1, длина строки получается функцией Length(Str):

for I:=1 to Length(Str) do begin
...
end;

8. В цикле получаем символ из строки:

Ch:=Copy(Str,I,1);

9. Пробуем получить данные из словаря по ключу, которым является русская буква. Если это удалось, присоединяем результат транслита к выходной строке, если нет — это не русская буква, присоединяем исходный символ к выходной строке:

if Dict.TryGetData(Ch, oTrans) then begin
	oStr:=oStr+oTrans; //russkaya bukva - transliteriruem
end
else begin
	oStr:=oStr+Ch; //nerusskaya bukva, ostavlaem v pokoe
end;

10. Освобождаем память словаря после цикла:

Dict.Free;

11. Возвращаем результат работы функции:

exit(oStr);

Функция целиком на PasteBin

12. Код основной программы:

var
    strInput, strOutput:string;
...
begin
  Write('Input string:'); ReadLn(strInput);
  strOutput:=Translit(strInput);
  WriteLn(strOutput);
  WriteLn('Press Enter...'); ReadLn();
end.

Для совместимости с русским языком в консоли необходимо добавить директивы компилятора, иначе словарь будет работать неправильно:

program translit;
{$mode objfpc} {H+}
{$codepage CP866}
...

$mode objfpc
H+ — чтоб строки по умолчанию не были ShortString‘ами
$codepage CP866 — установка кодовой страницы.

Документация по работе со строками

Проверка

Исходник примера на GitHub

Lazarus, поддержка русских букв в консоли (Windows 7)

Из коробки русские буквы в консоли поддерживаются через жопу:

Это потому что Lazarus по умолчанию создает файл в UTF8, а консоль Windows 7 поддерживает CP 866 (кодировку DOS/OEM), достаточно перекодировать файл:

1. Щелкаем по пустому месту в исходнике в редакторе.

2. Выбираем Параметры файла —> Кодировка

3. В выпадающем списке выбираем CP866:

4. В появившемся окне нажимаем кнопку Изменить файл:

5. ФАНФАРЫ!

Источник
Тестовый пример на GitHub

Lazarus, регулярные выражения.

Из коробки доступен мощный класс TRegExpr, вполне себе работает с регулярками. Сожрал даже C#-овскую, без изменения синтаксиса вообще. Пример регулярки для обнаружения русских букв:

program regexptest;
uses regexpr;
var  Regex:TRegExpr;

begin
     Regex:=TRegExpr.Create;
     Regex.Expression:='[а-я]|\s';
     Writeln(Regex.Exec('АБВГ'));
     Writeln(Regex.Exec('ABCD'));
     ReadLn();
end.

Документация
Пример на Киберфоруме

Этот пример на GitHub

UPD: Более лучшая регулярка для поиска кириллицы (и пробела).

[А-Я]|[а-я]|\s

Первая ([а-я]|\s) нормально работает, если формат файла исходника UTF-8, и текст в UTF-8, а вот с консолью в Win7 она работает только на строчных буквах, на заглавных не работает. А консоль требует CP866.

О других косяках кириллицы в консоли — в следующих выпусках нашего журнала.

Lazarus, список каталогов с подкаталогами

Плохо, что по маске не умеет каталоги искать. А в остальном все просто.

program alldirs;
uses Classes, SysUtils, FileUtil;
var
   lstDirs:TStringList;
   i: Integer;
begin
     lstDirs := TStringList.Create;
     FindAllDirectories(lstDirs,'C:\Windows',true);
     i:=0;
     while i < lstDirs.Count do begin
       WriteLn(lstDirs[i]);
       inc(i);
     end;
     WriteLn ('Found: ',lstDirs.Count);
     WriteLn ('Press Enter');
     lstDirs.Free();
     ReadLn();
end.

Ссылка на GitHub

Поигрался с Freepascal/Lazarus

Больше по служебной необходимости, и воле случая, чем по собственному желанию.
Инет отсутствовал, компы нормальные все заболели, а утилиту писать надо. Ще було, на том и писали.

Поиск файла

Наконец-то нормальный поиск файла, где маска файла работает как надо (как в DOS) и не принимает, например, расширение *.htm и *.html за одно и то же. C# мне не удалось этому очевидному решению научить, конечно, можно потом по выборке прогнать регулярное выражение, но оно тоже плохо срабатывает, упускает некоторые случаи, например, если имя файла начинается с расширения (т.е. на файл .html оно не сработает):

В Lazarus все работает из коробки:

program testfind;
uses Classes, SysUtils, FileUtil;
var
   lstFiles:TStringList;
   i: Integer;
begin
     lstFiles := TStringList.Create;
     FindAllFiles(lstFiles, 'C:\Temp\Test', '*.htm', true);
     i:=0;
     while i < lstFiles.Count do begin
       WriteLn(lstFiles[i]);
       inc(i);
     end;
     WriteLn ('Found: ',lstFiles.Count);
     WriteLn ('Press Enter');
     ReadLn();
     lstFiles.Free();
end.

Пример и каталог с тестовыми файлами на GitHub

UPD: Ссылка на мануал

Dyna Blaster for DOS (Бомбермен)

Родное demo игры:

По многочисленным просьбам зрителей, Werwolf сделал репак старой DOS-овской игры.

Под Windows XP и выше можно играть в DOSBOX последней версии (на момент написания заметки 0.74-3).

Добавлена возможность включения и отключения фоновой музыки:

Для включения надо запустить файл ONMUSIC.EXE, для выключения OFFMUSIC.BAT, по умолчанию фоновая музыка отключена.

Добавлен файл CHEATS.TXT с кодами для доступа к каждому уровню и кодом на бессмертие. Копия на PasteBin

Скачать

DYNA Blast for DOS с Mega.NZ(ZIP)

Скрипт для тестирования сетевых соединений. Инструкция.

Преамбула

Друзья из одной небольшой фиромочки попросили написать небольшой скрипт для тестирования соединений, чтобы быстро понять, где отвалилось. Например, упал роутер, не отвечает внутренний сервер, упал провайдер, или сдох VPN. Попросили сделать кросивое, с этим тоже справился, ошибки выделяются красным цветом, пройденные этапы зеленым, можно включить или отключить звуковое оповещение через PC-speaker.

Что умеет

+ Последовательно проводить два вида тестов: ping и получение страницы (или файла) с web-сервера
+ Оповещать пользователя об ошибках или пройденных тестах, с цветным текстом.
+ Выдавать звуковые сигналы об успешном завершении теста, или об ошибке на PC-speaker.

Для звуковых оповещений должен быть настроен PC-speaker и установлена утилита beep (копия).

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

Конфигурационный файл

Конфигурационный файл состоит из строк следующего формата:

операция|адрес|отображаемое описание|прервать/игнорировать

Пока поддерживаются только две операции:

ping — для ping’а адреса
getp — для получения страницы или файла с WEB-сервера (с помощью wget)

адрес — адрес, WWW для getp, IP или WWW для ping.

отображаемое описание — описание операции, текст, который будет выводиться на консоль.

прервать/игнорировать — при ошибке операции, если указано ключевое слово break, скрипт останавливает работу и выводит сообщение о том, что в ходе тестирования произошли ошибки. Если указать иное значение, например, skip, то скрипт продолжит производить тесты, пока не закончится конфигурационный файл, или пока не будет следующий сбой в тесте, где указана опция break.

Названия операций и break нечувстивительны к регистру (т.е. можно написать Ping, ping или Getp, GeTP или BreaK, breaK).

Первые два поля (операция и адрес) являются обязательными. Если они не будут указаны, скрипт будет прерван на строке с ошибкой:

...
Ping|192.168.0.1|Main router|break #Main router ping
ping|[ДАННЫЕ УДАЛЕНЫ]|Provider IP|break
getp
...

Если не будет указано поле описания, то оно будет по умолчанию установлено в значение No desription:

Если последнее поле не будет заполнено, то оно принимает значение break.

Если в первом поле будет неверно указанный код операции, то скрипт его проигнорирует, выдав соответствующее сообщение, продолжит выполнять другие операции, но завершится с ошибкой:

Ping|192.168.0.1|Main router|break #Main router ping
ping|[ДАННЫЕ УДАЛЕНЫ]|Provider IP|break
getp|[ДАННЫЕ УДАЛЕНЫ]|Provider page
1234|[ДАННЫЕ УДАЛЕНЫ]|VPN Server IP|break
ping|8.8.8.8|Internet IP|break
getp|google.com|Internet page|break

Для разделения полей используется символ |

В конфигурационном файле можно использовать комментарии, начинающиеся с символа #, все, что находится после этого символа — игнорируется. Пустые строки также игнорируются.

Пример конфигурационного файла (без данных)

#inettest.cfg example

Ping|192.168.0.1|Main router|break #Main router ping
ping|x.x.x.x|Provider IP|break #Change x.x.x.x to your provider ip
getp|myprovider.net|Provider site page|skip #change myprovider.net to real site your provider
ping|x.x.x.x|VPN Server IP|break #Change x.x.x.x to real VPN provider IP
ping|8.8.8.8|Internet IP|break
getp|google.com|Internet page|break

Переменные скрипта

Скрипт не имеет параметров командной строки, основные настройки осуществляются через переменные самого скрипта:

CONFIG — путь к конфигурационному файлу, например CONFIG="./inettest.cfg". Если конфигурационный файл не будет найден, скрипт выдаст ошибку:

CRITICAL ERROR: Config file ./inettest.cfg not exist!

NOCOLOR — если значение равно 0, включить вывод цветного текста на консоль, если 1 — отключить. По умолчанию 0

NOCOLOR=1:

NOSOUNDP — включение ( по умолчанию 0) или отключение (1) звука в процессе тестов. Звук выдается после каждого отдельного теста.
NOSOUNDF — аналогично предыдущей переменной, только звук звучит после окончания всех тестов или их прерывания.

NOADDR0, включить тестируемый адрес в вывод скрипта, 1 — не включать.

NOADDR=0:

NOADDR=1:

PACKETS — количество пакетов для команды ping (по умолчанию PACKETS=3)
TIMEOUT — тайм-аут для получения страницы или файла (в скрипте делается с помощью wget, по умолчанию TIMEOUT=5)

Тест при ошибке сети

Конфиг:

Ping|192.168.0.1|Main router|break #Main router ping
ping|[ДАННЫЕ УДАЛЕНЫ]|Provider IP|skip
getp|[ДАННЫЕ УДАЛЕНЫ]Provider page|skip
ping|[ДАННЫЕ УДАЛЕНЫ]|VPN Server IP|break
ping|8.8.8.8|Internet IP|break
getp|google.com|Internet page|break

Результат:

Коды ошибок

ping:
1 — No reply (не один из пакетов до пингуемого адреса не дошел)
2 — Other error (другая ошибка, в большинстве случаев — «сеть недоступна»).

getp (wget):
1 — Иная / общая ошибка (generic error code)
2 — Ошибка в параметрах командной строки или файлах конфигурации (.wgetrc или .netrc)
3 — Ошибка файлового ввода/вывода (I/O error)
4 — Ошибка сети (например, при обрыве связи)
5 — Ошибка SSL
6 — Ошибка идентификации (неправильное имя пользователя или пароль)
7 — Ошибка протокола
8 — Ошибка сервера (например, нужный файл на сервере не найден, ошибка 404)

Коды возврата скрипта

0 — Ошибок в ходе тестов не произошло.
1 — Произошла хотя бы одна ошибка.

Скачать

Репозиторий на GitHub

Linux: как проверить в скрипте, пингуется ли адрес.

Оказалось все очень просто.

ping <ip|url> -c <packets_count>

где:
<ip|url> — IP или URL адрес
ip — IP-адрес (например 8.8.8.8 или 192.168.0.1)
url — URL-адрес (например google.com)
<packets_count> — количество отправленных пакетов

В следующем примере мы пингуем google.com:

ping google.com -c 3

Вывод команды приводить не буду для экономии места, кому нужно, смотрите на PasteBin

Можно пропинговать и по IP, например, локальный роутер:

ping 192.168.0.1 -c 3

Вывод, опять же на PasteBin

Внимание! Количество отправленных пакетов (-с <число>), если вы используете ping в скрипте bash нужно указать обязательно, иначе команда ping никогда не прекратит свою работу и завесит скрипт, в отличии от команды ping в Windows (она по умолчанию посылает 5 пакетов и прекращает работу).

Коды возврата ping

Естественно, для анализа работы ping в скрипте, нам потребуются коды возврата.

К сожалению, в официальном man для команды ping их, почему-то забыли указать.

0 — Success (хоть один из пакетов дошел до адреса)
1 — No reply (не один из пакетов до пингуемого адреса не дошел)
2 — Other error (другая ошибка, в большинстве случаев — «сеть недоступна»).

На всякий случай

Если произошла ошибка с кодом 2, то команда ping выводит на stderr сообщение об ошибке, например:

ping 8.8.8.8 -c 3
connect: Network is unreachable

Отключение вывода

ping является полуинтерактивной командой, и показывает параметры отправленных пакетов (см. на PasteBin), если это не нужно, можно отключить вывод стандартным способом, перенаправив вывод команды ping из stdin и stderr в /dev/null, например:

ping 8.8.8.8 -c 3 >/dev/null 2>/dev/null

где:
>/dev/null — перенаправление stdin в нуль-устройство
2>/dev/null — перенаправление stderr в нуль-устройство

Пример

Простейшее использование команды ping в скрипте:

#!/bin/bash

#testping
# $1 - IP or URL address

ping $1 -c 3 >/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
    echo "Pinging!"
else
    echo "Not pinging!"
fi

Копия на PasteBin

Проверка

smallwolfie@wolfschanze:~/nettest$ ./testping 8.8.8.8
Pinging!
smallwolfie@wolfschanze:~/nettest$ ./testping 666.666.666.666
Not pinging!
smallwolfie@wolfschanze:~/nettest$ ./testping 192.168.0.55
Not pinging!
smallwolfie@wolfschanze:~/nettest$ ./testping example.org
Pinging!

Цветной текст в консоли Linux #3. Улучшаем совместимость скрипта.

Преамбула

Друзья [info]ketmar@ljr и [info]grusha@ljr отправили мне несколько ценных замечаний по поводу покраски консоли из скрипта (копия). Решил про них здесь отдельно написать, и модифицировать скрипт

Замечание #1, попадание ESC-последовательностей в поток, при вызове скрипта в потоке

Решил начать с него, оно более важное.
Впрочем, отдельно ему посвятил маленькую заметку (копия), где описал проблему и ее решение, так что осталось только применить, оборачиваю основной код функции echoc() в if, осушествляющий проверку, вызвали ли скрипт в терминале или в потоке:

if [ -t 1 ];then
	E__="\x1b[${FGROUND[$2]}m"
	if [ -n "$3" ];then
		E__="$E__\x1b[${BGROUND[$3]}m"
	fi

	if [ -n "$4" ];then
		E__="$E__\x1b[$4""m"
	fi

	echo -e "$E__$1\x1b[0m"

else
	echo "$1"
fi

Если не в терминале, просто выводим обычный текст без ESC-кодов:

В функции echocn() поступаем аналогично, просто к вызову echo не забываем добавить пареметр -n:

if [ -t 1 ];then	
	...
	echo -e -n "$E__$1\x1b[0m"

else
	echo -n "$1"
fi

Замечание #2. Совместимость цветов.

коды для яркости не входят в общепринятый стандарт VT-100, это расширение, и поддерживается далеко не всеми. один из стандартных способов увеличить яркость — включить полужирный режим: «\e[1;32m». да, это не работает для фона, стандартного метода для фона нет..

Т.е. максимально совместимыми цветами с терминалом являются только первые 7: коды 30..37 для текста, 40..47 для фона, дефолтные коды 39 и 49 для текста и фона соответственно (см. таблицу из предыдущей заметки (копия)).

Коды для яркости текста (90..97) и фона (100..107) расширение стандарта и поддерживаются не всеми терминалами. Для текста есть способ увеличить яркость — включить полужирный режим: семь цветов плюс полужирный с расчётом на то, что это давно уже яркость текста.

Совместимые цвета и стили

Итого, получаем вот такую таблицу совместимых цветов:

# Название цвета Код цвета текста Код цвета фона
0 Default (По умолчанию) 39 49
1 Black (Черный) 30 40
2 DarkRed (Темно-красный) 31 41
3 DarkGreen (Зеленый) 32 42
4 DarkYellow (Темно-желтый) 33 43
5 DarkBlue (Синий) 34 44
6 DarkMagenta (Темно-фиолетовый) 35 45
7 DarkCyan (Темный аквамарин) 36 46
8 Gray (Серый) 37 47
9 DarkGray (Темно-серый) 1;30
10 Red (Красный) 1;31
11 Green (Ярко-зеленый) 1;32
12 Yellow (Желтый) 1;33
13 Blue (Голубой) 1;34
14 Magenta (Фиолетовый) 1;35
15 Cyan (Аквамарин) 1;36
16 White (Белый) 1;37

Код сброса: \x1b[0m — сбрасывает настройки консоли (цвет текста, фона и стиль) к значению по умолчанию. Он работает нормально.

Заодно уж выбросил из таблицы стилей «мигающий» и «невидимый», которые объективно не работают:

Код стиля Стиль текста
0 Default (По умолчанию)
1 Bold (Жирный/яркость текста)
4 Understrike (Подчеркнутый)
7 Inversing (Инверсия), цвет фона и текста меняются местами

Модифицируем скрипт

Массивы с кодами цветов теперь выглядят так (массив с именами показан для лучшего понимания):

NAMES=(Default Black DarkRed DarkGreen DarkYellow DarkBlue DarkMagenta DarkCyan Gray DarkGray Red Green Yellow Blue Magenta Cyan White)
FGROUND=("39" "30" "31" "32" "33" "34" "35" "36" "37" "1;30" "1;31" "1;32" "1;33" "1;34" "1;35" "1;36" "1;37")
BGROUND=(49 40 41 42 43 44 45 46 47)

И подправляем вывод:

echo -e "Foreground color:\tBackground color:"

for N in {0..16}; do
    if [ $N -eq 1 ];then #foreground
	echocn "$N - ${NAMES[$N]}" $N 4
    else
	echocn "$N - ${NAMES[$N]}" $N
    fi
    echo -e -n "\t\t"
    
    if [ $N -le 8 ];then
	if [ $N -gt 1 ];then
	    echoc " ${NAMES[$N]} " 1 $N #background
	else
	    echoc " ${NAMES[$N]} " 0 $N
	fi
    else
	echo
    fi
done
echo
echocn "Default" 0 0 0; echo -n " "
echocn "Bold" 0 0 1; echo -n " "
echocn "Understrike" 0 0 4; echo -n " "
echocn "Inversing" 0 0 7; echo -n " "
echo
echo

Что получилось

Вывод в терминал:

Вывод в файл:

./esccolorscomp >test.txt

Замечание #3. Об использовании tput

Я задал вопрос, а не проще ли вместо ESC-кодов использовать tput, о чем я уже писал (копия). Ответ был таким: Он требует установленого ncurses, в общем и целом — никто не гарантирует его наличия.

Готовый скрипт

На GitHub

Электронная книга Dexp M8 Prudentia, драйвера для Windows 7.

Немала баба клопоту, купила порося, в смысле немал клопоту я, но повелся на скидку и связался с дерьмоконторой DNS и ее клоном DEXP. Прошлая книжка у меня была Амазон Киндл, и я ее еще в Киеве купил, впрочем, так бы ей и пользовался, если бы на нее жопой не села бухгалтерша. Напрягать тетку не стал, выбрал чего подешевле. Естественно, задача была перекинуть книжки с той на эту, и если эту у меня винда прекрасно видела, то видеть эту наотрез отказалась.

На сайте говно-DNS, дерьмо-DEXP и в сраной инструкции естественно, «это ж хуй, я вопрос отгадала», т.е. не драйверов, ни того, где их искать. Т.е контора просто пиздец клиентоориентированная. Кроме флешек вообще лучше ничего у них не покупать. Правда, кнопочные телефоны DEXP еще хорошие, у правильного дядюшки Ляо заказывают, кирпич неубиваемый от слова «даже об голову Кивы».

Пришлось для простейшего подключения андроидной железяки включать мозг и заниматься детективным расследованием, правда, довольно простым.

Железка под Андроидом 8.1 и на чипе Rockchip PX30, так что подошли драйвера Rockchip 4.4

На всякий случай забэкапил

Rockchip Driver Assitant v4.4 на Mega.NZ (10 Mb, RAR)

Как проверить, вызван ли скрипт из терминала, или вывод скрипта перенаправлен в поток.

Как проверить, вызван ли скрипт из терминала, или вывод скрипта перенаправлен в поток.

Преамбула

А зачем? Это логическое продолжение темы (копия) про покраску текста в терминале. Если использовать ESC-последовательности, то они, что логично, попадут в файл, если пользователь перенаправит туда вывод скрипта, и получится бяка:

Потому, надо проверить, вызвали ли скрипт из терминала, или вывод скрипта перенаправлен в поток.

Решение

По итогам обсуждения с [info]ketmar@ljr и [info]grusha@ljr решение нашлось:

if [ -t 1 ];then
    echo -e "\x1b[32;1mRun in terminal\x1b[0m"
else
    echo "Run in pipe"
fi

Проверка

Вызов из терминала:
./testpipe
Run in terminal

Вызов в потоке:
./testpipe >test.txt

Содержимое файла test.txt:
Run in pipe

Тестовый скрипт

на GitHub

Цветной текст в консоли #2

Преамбула

Мы уже красили консоль при помощи tput (копия), но есть лучший способ, при помощи эскейп-последовательностей, там немного сложнее и запутаннее синтаксис, но зато нормальная поддержка 16 цветов и стилей.

ESC-последовательности

ESC-последовательность это код, который вставляется в вызов команды echo или printf перед, после или прямо посреди текста, который мы собираемся выводить.

Синтаксис кода такой: \x1b[???m, где вместо ??? надо вставить код цвета текста, фона или стиля текста. Коды можно перечислять через точку с запятой: \x1b[???;???;???m или несколько кодов подряд: \x1b[???m\x1b[???m\x1b[???m. 1b — это код символа ASCII 27, который соответствует коду клавиши ESC (откуда и название).

Коды цвета и фона

# Название цвета Код цвета текста Код цвета фона
0 Default (По умолчанию) 39 49
1 Black (Черный) 30 40
2 DarkRed (Темно-красный) 31 41
3 DarkGreen (Зеленый) 32 42
4 DarkYellow (Темно-желтый) 33 43
5 DarkBlue (Синий) 34 44
6 DarkMagenta (Темно-фиолетовый) 35 45
7 DarkCyan (Темный аквамарин) 36 46
8 Gray (Серый) 37 47
9 DarkGray (Темно-серый) 90 100
10 Red (Красный) 91 101
11 Green (Ярко-зеленый) 92 102
12 Yellow (Желтый) 93 103
13 Blue (Голубой) 94 104
14 Magenta (Фиолетовый) 95 105
15 Cyan (Аквамарин) 96 106
16 White (Белый) 97 107

Код сброса: \x1b[0m — сбрасывает настройки консоли (цвет текста, фона и стиль) к значению по умолчанию.

Коды стиля текста

Код стиля Стиль текста
0 Default (По умолчанию)
1 Bold (Жирный)
4 Understrike (Подчернкутый)
5 Blinking (Мигающий), не работает, получается серый текст на темно-сером фоне
7 Inversing (Инверсия), цвет фона и текста меняются местами
8 Invisible (Невидимый), не работает

Тестовый скрипт

1. Проще всего покласть названия цветов, а также коды цвета и фона в массивы:

NAMES=(Default Black DarkRed DarkGreen DarkYellow DarkBlue DarkMagenta DarkCyan Gray DarkGray Red Green Yellow Blue Magenta Cyan White)
FGROUND=(39 30 31 32 33 34 35 36 37 90 91 92 93 94 95 96 97)
BGROUND=(49 40 41 42 43 44 45 46 47 100 101 102 103 104 105 106 107)

2. Создадим функцию echoc(), принимающую три параметра, цвет текста, цвет фона и стиль:

echoc() #Text, color, background, attributes
{
    ...
         Тут будет код
    ...
}

Внутри функции:

if [ -z "$2" ];then
	echo "$1" 
	return 
fi

Если второго параметра нет, просто вызываем echo и выходим из функции.

E__="\x1b[${FGROUND[$2]}m"

Второй параметр, номер кода цвета текста в массиве, формируем ESC-последовательность с ним во временную переменную.

if [ -n "$3" ];then
	E__="$E__\x1b[${BGROUND[$3]}m"
fi

Если есть третий параметр — добавляем ESC-последовательность для цвета фона.

if [ -n "$4" ];then
	E__="$E__\x1b[$4""m"
fi

Если есть четвертый — добавляем код для стиля текста (1, 4, 5, 7, 8), см. таблицу выше.

echo -e "$E__$1\x1b[0m"

Выводим текст:

-e — параметр, позволяющий команде echo обрабатывать ESC-последовательности.
$E__ — переменная, в которой сформирована ESC-последовательность.
$1 — выводимый текст.
\x1b[0m — после текста вставляем код сброса.

3. Создаем функцию echocn(), которая от функции echoc() отличается одной строчкой:

echo -e -n "$E__$1\x1b[0m"

где -n — вывести текст без перевода строки

4. Выводим в цикле названия цветов, и примеры цвета и фона:

echo -e "Foreground color:\tBackground color:"

for N in {0..16}; do
    if [ $N -eq 1 ];then #foreground
	echocn "$N - ${NAMES[$N]}" $N "16"
    else
	echocn "$N - ${NAMES[$N]}" $N
    fi
    echo -e -n "\t\t\t"
    
    if [ $N -gt 1 ];then
	echoc " ${NAMES[$N]} " 1 $N #background
    else
	echoc " ${NAMES[$N]} " 0 $N
    fi
done

5. И тестируем стили:

echo
echocn "Bold" 0 0 1; echo -n " "
echocn "Understrike" 0 0 4; echo -n " "
echocn "Blinking" 0 0 5; echo -n " "
echocn "Inversing" 0 0 7; echo -n " "
echocn "Invisible" 0 0 8; echo -n " "
echo
echo

Результат — в скрине в начале поста

Готовый скрипт

На GitHub

По мотивам

Как изменить цвет текста в терминале Linux

Отключение проверки сертификатов в curl

Преамбула

При использовании скрипта 0x0.sh, из предыдущего поста (копия), внезапно напоролся на ошибку curl: (60) SSL certificate problem: certificate has expired.

Грешным делом подумал, что у меня в системе протухли корневые сертификаты, поскольку слаку я триста лет не обновлял, уже лет 5 без переустановки стоит, даже пошел, и нашел как их вроде бы стандартным способом обновить. Недопомогло. Потом думаю, если бы сертификаты все совсем были старые и просроченные, у меня бы ничего не работало, ни curl, ни wget, ни браузеры, ни ютупчик. А тут вроде как всего один сайтик, что-то тут не то, или я не так делаю, или на сайте косяк. Неделю проебавшись, пошел спросил у более знающего юзера [info]ketmar@ljr. Да отключи ты их к лешему, или опциями командной строки, или на уровне конфига, ответил он.

Отключение проверки сертификатов в curl на уровне пользовательского конфига.

curl, перед проверкой параметров командной строки, заглядывает в свой конфиг в каталоге пользователя, так что в нем можно установить локальные (относительно пользователя) параметры по умолчанию. Нас интересует опция отключения проверки сертификатов.

1. Заходим в свой домашний каталог (/users/<ваше_имя пользователя>/)
2. Создаем файл .curlrc
3. Прописываем в нем одну строчку: insecure

Отключение проверки сертификатов в curl в скрипте

Достаточно добавить параметр -k или --insecure до параметров -F "file=@<имя файла>", если вы curl‘ом что-то отправляете, или до адреса URL, если вы curl‘ом что-то получаете.

Например, я модифицировал код скрипта 0x0.sh:

Было:
...
url=$(curl ${curl_opts} -F "file=@${file}" "${host}")
...

Стало:
...
url=$(curl ${curl_opts} --insecure -F "file=@${file}" "${host}")
...

Было:
...
shortened=$(curl ${curl_opts} -F "shorten=${url}" "${host}")
...

Стало:
...
shortened=$(curl ${curl_opts} --insecure -F "shorten=${url}" "${host}")
...

Было:
...
uploaded=$(curl ${curl_opts} -F "url=${url}" "${host}")
...

Стало:
...
uploaded=$(curl ${curl_opts} --insecure -F "url=${url}" "${host}")
...

Заработало!

smallwolfie@wolfshanze:/tmp# 0x0.sh -f 332068.jpg
uploading "332068.jpg"...
######################################################################## 100.0%
https://0x0.st/o4_0.jpg

Котик

Конечно же котролирующий передачу, развертку по горизонтали и вертикали, и держащий под котролем изображение и звук.

Ну и пропатченный скрипт

На GitHub

Скрипт для постинга на файл-хостинг 0x0.st

Есть прикольный файл-хостинг 0x0.st, но постить на него можно только скриптом. Мопед не мой, просто оставлю его здесь.

На GitHub

Copyright 2016-2018 Kylie McClain <kylie@somas.is>

Краткая справка по использованию скрипта

Использование: 0x0.sh [-f <file>] [-s <url>] [-u <url>] [file]
Если файл не указан, скрипт загружает поток stdin

-f <file> - загрузить <файл>
-s <url> - шортинг адреса <url> (В настоящее время не поддерживается сервисом!)
-u <url> - загрузка содержимого по адресу <url>

Цветной текст в консоли Linux #1

Преамбула

Захотел я как-то украсить скрипт, ну чтоб он не был таким скучным, и подумал — в DOS можно было красить консоль, а можно ли в Linux? Можно!

Красим с помощью tput

tput — команда, в основном предназначающаяся для управления консольным курсором, но покрасить она тоже может, хоть и довольно хреново.

Общий синтаксис:

tput <команда> <параметры>

В нашем случае, интересуют команды, изменяющие цвет или стиль текста.

Для удобства сведу их в таблицу:

Команда tput Действие
bold Жирный текст, после вызова команды
smul Начало подчеркнутого текста
rmul Конец подчеркнутого текста
rev Реверс текста и фона, т.е. они меняются местами
blink Мигающий текст (не на одной консоли не сработал)
invis Невидимый текст (у меня не сработало)
smso Некий «выдающийся» (standout) режим, отличий при выводе не заметил
rmso Отключить «выдающийся» режим
setaf <код_цвета> Установить цвет текста
setab <код_цвета> Установить цвет фона
sgr0 Сбросить настройки терминала к значениям по умолчанию.

Коды цвета

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

Код цвета Цвет
0 Черный (Black)
1 Красный (Red)
2 Зеленый (Green)
3 Желтый (Yellow)
4 Голубой (Blue)
5 Фиолетовый (Magenta)
6 Светло-голубой (Cyan)
7 Белый (White), у меня почему-то не сработал.
8 Не используется
9 Возврат к цвету по умолчанию

Как использовать

Я написал тестовый скрипт, где последовательно перебираю цвета текста и цвета фона:

tput setaf <код_цвета>, для текста
tput setab <код_цвета>, для фона
потом echo -n "некий текст", где некий текст — наименование цветов в массиве, см. исходник.

А потом вызываю tput sgr0, чтобы сбросить консоль.

Стили текста:

echo "Text style:"
tput bold; echo "Bold"; tput sgr0
tput smul; echo "Underlined"; tput rmul
tput rev; echo "Reversed"; tput sgr0
tput blink; echo "Blinking"; tput sgr0
tput invis; echo "Invisible"; tput sgr0
tput smso; echo "Standout"; tput rmso

tput sgr0

Что получилось

Исходник на GitHub

Смотреть здесь

Источник

tput, на буржуйском. Копия в PDF

Утечки DNS, что это такое, как справиться, как проверить, чем грозит.

Преамбула

Крошка юзер пришел к админу, и спросила кроха — VPN себе купил, все равно, бля банят.
Практически реальная история одного юзера, т.е. он купил себе малоизвестный, потому и неизвестный роскомкозлам VPN, пошел почитать kasparov.ru, а получил вот это:

Стали разбираться, VPN абсолютно не российский, сделанный двумя бразильскими рэперами-анархистами, логов не ведет, не является сторонним сервисом, поставляющим чужие услуги, просто пропуская трафик через себя, русских нод выхода нет. Значит, утечка DNS, т.е. VPN-провайдер позволяет использовать другие (кроме локального для провайдера VPN) DNS, а у провайдера прописан глобальный DNS-сервер. У Говнотелекома именно так.

Что такое DNS, объясняю по рабоче-крестьянски.

DNS расшифровывается как Сервер доменных имен. Один хрен, непонятно. Если совсем просто — это телефонный справочник. Или справочная служба. Например, вам хочется позвонить Вербицкому Михаилу Сергеевичу в Москве по такому-то адресу, но номера вы не знаете. Звоните в справочную службу 018, и вам говорят номер.

Сейчас, конечно, нет телефонных служб и телефонных справочников, но представьте себе свой мобильник, мама у вас записана, как «Мамочка», жена, как «Любимка», брат, как «Саня Мелкий», а любовница, как «Иван Михалыч», а рядом с их именем отображается номер телефона.

Интернет изначально не предполагал, что вообще будут какие-то имена сайтов, типа google.com (и вообще он выйдет за границы военного ведомства США), и компьютеры получали IP-адреса, состоящие из цифр с точкой, например google.com имеет IP-адрес 142.251.36.14

Когда интернеты таки вылезли за границы DARPA и стали гражданской технологией, всем стало понятно, что юзверю неудобно набирать кучу цифири в адресной строке, т.е. 142.251.36.14 вместо google.com умные люди придумали систему DNS, т.е. браузер сначала обращается к специальному серверу, который сопоставляет имя сайта, например, того же google.com с его IP-адресом, и все должно заверте…

Дыры в DNS

Минус системы DNS в том, что запросы к DNS изначально не шифруются, соответственно, перехватить запрос и узнать, к какому сайту вы обращаетесь, или даже подменить запрос, и перенаправить на фишинговый сайт может любой, кто знает ваш IP и адрес DNS-сервера. Вторым способом, кстати, провайдеры осуществляли блокировку доступа к забаненным говнокомнадзором сайтам, ну и сейчас, как видите, осуществляют.

Потом, конечно, фатальный недостаток постарались исправить, навешав на старый протокол DNSSEC, который тоже всей беды не решает, DOH или DoT, но один черт, не все сервера поддерживают новые расширения протокола, так что до конца эта беда по-прежнему не решена.

Проверка на утечки DNS (DNS-leaks)

Существует множество онлайн-сервисов, проверяющих утечки DNS, их реально очень много, практически у каждого крупного VPN-провайдера такой есть, есть и не у VPN-провайдеров, а сами по себе. Один из самых популярных https://www.dnsleaktest.com/

Включаете JavaScript в браузере (если выключен) и нажимаете кнопку Extended Test:

Вот, что у меня получилось:

Утекает, но на Запад, что хотя бы не так страшно.

Пробуем другой сервис, например, берем самый первый из запроса «тест утечки DNS», у меня это https://whoer.net/ru/dns-leak-test.

Как и выше, тестирую на офисной машине в своем офисе:

Иерархия запросов DNS

Звучит страшно, но на самом деле все просто, DNS-запрос сначала обрабатывает ОС, установленная на данном компьютере, а потом, все вышеследующие системы по соединению.

Например, представим ситуацию:

1. У вас есть локальный компьютер в квартире.
2. В квартире есть роутер или даже домашний сервер.
3. На сервере подключен VPN-провайдер.

При запросе к сайту (любому), система сначала будет обращаться к локальным (т.е. компьютера) настройкам DNS, если доступ есть, то DNS-запрос будет отправлен на тот адрес, который будет указан в настройках. Если локальные настройки DNS не указаны прямо или не получаются автоматически, то система обратится к соединению с сервером/роутером, и получит настройки от него. Аналогично и сам сервер/роутер — он обратится к DNS-серверу нужного провайдера, конечно, если все настроено правильно.

Соответственно, большинство утечек решаются правильной настройкой DNS на нужных устройствах, на крайний случай, обращением к провайдеру услуг. Если добросовестный, то поправит.

Стандартные варианты конфигурации DNS и шлюза в Windows 7

Можно посмотреть в графическом интерфейсе, и схонфигурировать нужную конфигурацию для Windows 7.

Нужно зайти в Сеть и Интернет —> Сетевые подключения а потом найти основной адаптер, а потом протокол IPv4, и посмотреть как настроено (открыть пункт Протокол Интернета версии 4), теперь нажимаем Свойства и смотрим:

Ага, тут DNS выбирается автоматически.

А вот, как сделано на рабочей машине:

Т.е на иллюстрации видно, что DNS и шлюз не прописаны. Такая конфигурация используется для локального (корпоративного) VPN, где сервер доступен вам из локальной сети, а рабочая станция вообще не может обратиться к Интернету, если соединение с VPN «упадет».

Есть и третий вариант конфигурации — оставляем основной шлюз, например, основного провайдера, но DNS не прописываем. Не самый безопасный вариант, но используется, если VPN-провайдер вне локальной сети, т.е. компьютер связывается с провайдером VPN в Интернете, а тот уже сам назначит DNS-сервера, создав отдельное соединение, а в соединении с основным провайдером, DNS-сервера просто не будут указаны:

Посмотреть конфигурации DNS для всех существующих соединений

Как я уже говорил выше, вышестоящее сетевое соединение (например VPN) может переопределить DNS, потому можно посмотреть DNS для всех существующих соединений через консоль:

ipconfig /all|more

А вот и утечка!

...
Адаптер PPP lainserexp:

   DNS-суффикс подключения . . . . . :
   Описание. . . . . . . . . . . . . : lainserexp
   Физический адрес. . . . . . . . . :
   DHCP включен. . . . . . . . . . . : Нет
   Автонастройка включена. . . . . . : Да
   IPv4-адрес. . . . . . . . . . . . : 172.16.1.122(Основной)
   Маска подсети . . . . . . . . . . : 255.255.255.255
   Основной шлюз. . . . . . . . . : 0.0.0.0
   DNS-серверы. . . . . . . . . . . : 8.8.8.8
                                       10.x.x.x
   NetBios через TCP/IP. . . . . . . . : Включен

Внутренний корпоративный VPN оказался криво настроен — первым DNS-сервером выдает гуглевский 8.8.8.8, а локальный вторым. Звоним администратору, пусть меняет конфигурацию.

Настройки DNS в Linux

Настройки DNS в Linux хранятся в файле /etc/resolv.conf, который представляет собой обычный текстовый файл, потому посмотреть и отредактировать его можно любым удобным текстовым редактором.

Содержимое файла /etc/resolv.conf в котором, например, указаны публичные DNS-серверы Google:

nameserver 8.8.8.8
nameserver 8.8.4.4

Просмотр DNS в Linux

В Linux DNS также может быть изменен сетевым соединением, и тоже есть возможность это проверить.

1. С помощью команды dig

dig google.com

Вывод (оставил только значимый результат):

...
;; ANSWER SECTION:
google.com. 300 IN A 142.251.36.14

;; Query time: 44 msec
;; SERVER: 10.10.0.1#53(10.10.0.1)
;; WHEN: Sat Jul 09 11:57:58 AKDT 2022
;; MSG SIZE rcvd: 55

В строке SERVER указан использованный сервер DNS (10.10.0.1) и порт (53), заодно, можно увидеть и IP-адрес сайта (142.251.36.14)

2. Командой nslookup:

nslookup google.com

Вывод:

Server:         10.10.0.1
Address:        10.10.0.1#53

Non-authoritative answer:
Name:   google.com
Address: 142.251.36.14

Так же виден адрес используемого DNS-сервера и его порт и адрес сайта, к которому обратилась команда.

Потом расскажу, как сделать локальный DNS-сервер в сети или на локальной машине.

Источники

1. Как скрыть Реальный DNS и почему его видно
2. Как мне узнать, какой DNS-сервер использовать?
3. Как узнать IP DNS сервера в Linux

Копии источников в одном архиве (RAR, PDF)

Отключение обновления Foxit PDF Reader (v. 8.3.2.25013)

Преамбула

Когда-то писал о том, что в новых версиях Foxit Reader пропал PDF-принтер и Foxit PDF Creator (копия). Так вот, новая гадость пришла откуда не ждали, теперь он сносит PDF-принтер при обновлениях.

Штатного способа отключить обновления нет

Решение

Сама программа обновления имеется в двух экземплярах:

В каталоге Foxit:
C:\Program Files (x86)\Foxit Software\Foxit Reader\FoxitUpdater.exe

И в каталоге Application Data:
C:\Users\<username>\Application Data\Foxit Software\Addon\Foxit Reader\FoxitReaderUpdater.exe, вместо <username> — ваше имя пользователя.

Просто снести два экзешника не получится, точнее получится, но Foxit Reader будет при каждом запуске ругаться, что не нашел свой обновлятор. Зато не будет ругаться, если обновлятор (оба файла) просто заменить на экзешник, который ничего не делает, а такой я уже делал (копия), правда по другому поводу. Сделал еще и версию на MASM

Написал патч на NSIS

И для себя, если винды переустанавливать, и для клиентов, на всякий случай.

Репозиторий на GitHub
Исходник NSIS
Копия (без дополнительных файлов) на PasteBin
Скачать готовый патч

Дополнительно

В принципе, исходник достаточно простой, оставлю только ссылку на получение MD5-суммы файла в NSIS: NSIS: контрольная сумма (MD5), сравнение файлов. (копия).

Примечание: почему-то MD5-сумма, получаемая NSIS-плагином (md5dll.dll) отличается от MD5-суммы, полученной средствами Windows (копия). Почему, пока не разобрался. Может, позже напишу.