Вопрос по работе с bash из правил

Здравствуйте.

Необходимо периодически отправлять команду на удаленный com порт. Если выполняю в консоли, то все работает

echo -e '\x51\x50\x49\x47\x53\xB7\xA9\x0D' | netcat -i1 -N 192.168.1.19 20108

Сервер корректно отвечает. Но когда в коде правил выполняется строка

runShellCommand("echo -e '\x51\x50\x49\x47\x53\xB7\xA9\x0D' | netcat -i1 -N 192.168.1.19 20108",{
    captureOutput: true, 
    exitCallback: function (exitCode, capturedOutput) 
    {
      	log("response: " + capturedOutput);
     }
   })

то сервер отвечает, что команда не распознана. Пробовал с двойными кавычками, экранировал их и слешы - все равно не получается.

Подскажите, в чем может быть проблема?

Добрый день!

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

runShellCommand("echo -e '\\x51\\x50\\x52\\x53' | nc -w 1 192.168.1.100 1234", {
    captureOutput: true
}, function (output) {
    log("Shell command output: " + output.stdout);
});

Убедитесь, что адрес и порт заданы верно. Если потребуется дополнительная помощь, дайте знать!

Проверил - не заработало.

Может, как-то в логах ОС можно посмотреть, что уходит?

Запустил nc на другой машине и туда отправил сообщение
image

Оказалось, что параметр -e и пробел то же отправляются. Как-то странно работает?

Поскольку вся конструкция в кавычках передаётся как есть, я правильно понимаю, что данные успешно передались с контроллера? Е

Нет, не успешно. Данные из правил передаются вместе с параметром и с символами, которые находятся до внутренних кавычек
image

Решил проверить по другому. Переделал вывод в правилах

    runShellCommand("echo " + "\x51\x50\x49\x47\x53\xB7\xA9\x0D" + " | nc -w1 192.168.1.10 8083",{
    	captureOutput: true, //Захватывать stdout
    	captureErrorOutput: true, //Захватывать stderr (если нужно)
    	exitCallback: function (exitCode, capturedOutput, capturedErrorOutput) //Функция, в которую попадает вывод
        {
        	log("cmd output: " + capturedOutput); //строка полностью
        	log("cmd Erroroutput: " + capturedErrorOutput); //Если нужен вывод stderr
        }
    })

Запустил на 192.168.1.10 прослушивание порта с выводом в файл

sudo nc -nlv 8083 > nc-rez

Если на контролере выполнить команду в консоли

 echo -e '\x51\x50\x49\x47\x53\xB7\xA9\x0D' | nc -w1 192.168.1.10 8083

то файл получается размером в 9b
2024-12-23_16-08-47
2024-12-23_16-06-55
Такая команда и должна прийти

Но если команда отправляется из кода правил, то файл становится размером в 11b
2024-12-23_16-17-11
2024-12-23_16-16-53

Появляются непонятные 2 байта
image

Что с этим можно сделать?

Случайно заглянул.

//12_23_test_01.js
spawn('bash', ['-c', "/usr/bin/printf '\x51\x50\x49\x47\x53\xb7\xa9\x0d' | nc -w 1 10.0.0.75 7777"],{  
   captureOutput: true, //Захватывать stdout   
   captureErrorOutput: true, //Захватывать stderr (если нужно)             
 exitCallback: function (exitCode, capturedOutput, capturedErrorOutput) //Функция, в которую попадает вывод
   {
   	 log("cmd output: " + capturedOutput); //строка полностью
     log("cmd Erroroutput: " + capturedErrorOutput); //Если нужен вывод stderr
   }
})
  • да, генерирует 51 50 49 47 53 C2 B7 C2 A9 0D
    Но. “/usr/bin/printf ‘\x51\x50\x49\x47\x33\x34\x35\x36’ | nc -w 1 10.0.0.75 7777” возвращает 51 50 49 47 33 34 35 36 - как и ожидается. То есть дело, ИМХО, в локали. 0xb7, 0xa9 - из верхней половины таблицы. Если ее, локаль, явно задать - должно работать. Ну или вызов в bаsh скрипт оформить.
1 лайк

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

Переделал вывод c использованием printf, таже самая история - добавляет 2 байта
image

Вообщем создал bash файл с этой командой и его запускаю. Спасибо !

Ну потому что если в консоли из-под пользователя выполнить locale то вернется:

locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

А их скрипта, для примера:

  spawn('bash', ['-c', "locale"],{  
   captureOutput: true, //Захватывать stdout     
   captureErrorOutput: true, //Захватывать stderr (если нужно)             
 exitCallback: function (exitCode, capturedOutput, capturedErrorOutput) //Функция, в которую попадает вывод 
   {
   	 log("cmd1 output: " + capturedOutput); //строка полностью
     log("cmd1 Erroroutput: " + capturedErrorOutput); //Если нужен вывод stderr
   }
})      

Вернет UTF-8

2024-12-24 13:48:40cmd1 output: LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=

Cоответственно, все символы с кодом больше 0x7F - кодируются двумя байтами.
Хотя - если явно задать кодировку

"LC_ALL=POSIX /usr/bin/printf '\x51\x50\x49\x47\x53\xb7\xa9\x0d' | nc -w 1 10.0.0.75 7777"

То тоже отправляет UTF. В общем - вариант с скриптом лучше, да.

1 лайк

Большое спасибо ! Много нового для себя узнал.