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

21.07.20

Разработка - Механизмы платформы 1С

О запуске сторонних приложений и скриптов из кода встроенного языка платформы 1С.

Необходимость

Платформа 1С великолепна, замечательна и просто мощная. Обширный функционал доступен из коробки, а технология внешних компонент делает ее практически безграничной в части расширения возможностей. Но иногда...

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

&НаСервере
Процедура ВыполнитьБесконечныйПинг()

	ЗапуститьПриложение("ping 127.0.0.1 -t");
	
КонецПроцедуры

Сегодня мы поговорим о запуске приложений программным способом. А также о некоторых проблемах и способах их решений под Windows и Linux.

Часть подходов, которые будут описаны ниже, применяются в разработке "Командный интерпретатор для 1С", но скачивать ее для изучения не обязательно. Все есть здесь. Там лишь все это организовано в удобном виде для использования.

Исполни это

Причин, когда такое может понадобиться - много, очень много. Все их рассматривать точно не будем. Остановимся на одном простейшем примере - запуск команды ping, чтобы узнать доступность какого-либо ресурса в сети средствами 1С. Иногда еще ping запускают для эмулирования ожидания (метода Sleep), но мы такое извращение делать не будем :)

Наша задача - запустить какое-либо приложение с параметрами и получить результат его работы. И сделать мы это должны безопасным способом!

Последнее означает, что если запускаемое приложение зависнет, запросит интерактивных действий от пользователя (а на сервере мы ничем ему в этом случае помочь не сможем) или просто будет выполняться дольше выделенного для него времени, то мы должны завершить его работу и продолжить выполнение кода в обычном режиме и обработать исключение. Никому ведь не нужны зависшие сеансы 1С?

Мы рассмотрим несколько решений как для Windows, так и для Linux. И так, поехали.

My Little Windows

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

 
 Служебные процедуры и функции

Решения не идеальные, но простые. Например, там можно найти как сохранить файл в кодировке UTF-8 без BOM, получить путь к файлу PowerShell.exe и др. Решения всегда можно улучшать.

Плохой пример

И так, как обычно выполняется запуск приложений из кода встроенного языка? Правильно - с помощью процедуры "ЗапуститьПриложение()":

ЗапуститьПриложение(<СтрокаКоманды>, <ТекущийКаталог>, <ДождатьсяЗавершения>, <КодВозврата>)

Первым параметром передаем строку команды запуска и параметры по необходимости. Во втором устанавливаем каталог, что не обязательно. Третий параметр позволяет дождаться завершения приложения, а четвертый получить код возврата. Обычно если код возврата не равен 0, значит что-то пошло не так.

Вернемся к нашей задаче. Выполним команду "ping infostart.ru". 

// Временный файл для сохранения вывода результата на консоль
ПутьКФайлуРезультата = ПолучитьИмяВременногоФайла("log");;

// Формируем текст команды для запуска. Здесь может быть произвольный текст команды или даже целый скрипт.
КомандаЗапуска = "ping infostart.ru > ""{ПутьКФайлуРезультата}""";
КомандаЗапуска = СтрЗаменить(КомандаЗапуска, "{ПутьКФайлуРезультата}", ПутьКФайлуРезультата);

// Сохраняем команду запуска в файл исполняемого скрипта BAT.
// Это нужно для обхода различных ограничений работы процедуры "ЗапуститьПриложение",
// которая некоторые команды не может обрабатывать корректно
ФайлСкрипта = ПолучитьИмяВременногоФайла("bat");
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(КомандаЗапуска);
ТекстовыйДокумент.Записать(ФайлСкрипта, "cp866");

// Запускаем сформированный BAT-скрипт на выполнение
КодВозврата = Неопределено;
ЗапуститьПриложение(ФайлСкрипта,, Истина, КодВозврата);

Если КодВозврата = 0 Тогда
	// Если ошибок при выполнении нет, то получаем строку вывода результата
	ТекстовыйДокуменнт = Новый ТекстовыйДокумент;
	ТекстовыйДокуменнт.Прочитать(ПутьКФайлуРезультата, "cp866");
	ТекстРезультат = ТекстовыйДокуменнт.ПолучитьТекст();
Иначе
	// Иначе вызываем исключение
	ВызватьИсключение "Ошибка выполнения команды. Код возврата: " + КодВозврата;
КонецЕсли;

// Удаляем временные файлы
УдалитьФайлЕслиВозможно(ФайлСкрипта);
УдалитьФайлЕслиВозможно(ПутьКФайлуРезультата);

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

В качестве решения может быть реализация таймаута выполнения команды, но для процедуры "ЗапуститьПриложение" такое реализовать практически невозможно. Можно, конечно, попробовать запустить приложение и ожидать файла-результата какое-то время, но это решит проблему частично. Зависания не будет, но приложение будет запущено и дальше, ожидая внешней команды.

WScript.Shell нас спасет

Мы же в среде Windows. Давайте используем ее средства в виде COM-Объекта "WScript.Shell":

 
 Безопасный запуск команды / скрипта через WScript.Shell

Теперь приложение не зависнет и в случае чего мы сможем завершить его работу принудительно.

 Мое имя Power, PowerShell

Пойдем дальше и сделаем наше решение более интересным. Что, если нам нужно запустить не простую команду CMD или BAT'ник, а команду или скрипт PowerShell, но на тех же условиях! Для примера опять же оставим запуск бесконечного пинга :)

 
 Запускаем безопасно скрипты PowerShell

Фактически, теперь можно запускать любые скрипты хоть CMD, хоть PowerShell. А если сильно хочется, то можно и GIT Bash под Windows использовать или даже подсистему WSL под Windows 10. Но все это уже другая история. Осталось поговорить про Linux.

*.nix is my own

Под *.nix привычнее всего использовать bash для выполнения команд. Можно ли использовать bash из встроенного языка платформы 1С? Да, можно. Можно запускать как отдельные команды, так и целые скрипты. При этом получать результат и, что самое главное, делать это безопасно как в примерах выше.

В далеком 2015 году на Mista была поднята тема "Запуск файлов *.sh в самой 1с". Возможно, информация ниже будет ответом на вопрос, т.к. точного ответа так там и нет. Но может быть я не прав :)

 Запускаем bash-скрипты

Первое, что нужно понять - в Linux нет COM-объектов. Значит придется обойтись штатными средствами платформы 1С. Выглядеть это будет так:

// Задаем параметры
ТаймаутВыполненияСек = 10;
ТекстКомандыДляВыполнения = ТекстКоманды;

// Подготавливаем временные файлы
ФайлСкрипта = ПолучитьИмяВременногоФайла("sh");
ФайлРезультатСкрипта = ПолучитьИмяВременногоФайла("log");

// Подготавливаем файл скрипта
ПереносСтроки = Символы.ПС;
ЗаписьТекста = Новый ЗаписьТекста(ФайлСкрипта, КодировкаТекста.UTF8, ПереносСтроки);
ЗаписьТекста.ЗаписатьСтроку("#!/bin/sh");
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.Записать(ТекстКомандыДляВыполнения);
ЗаписьТекста.ЗаписатьСтроку("");
ЗаписьТекста.Закрыть();

// Конвертируем файл скрипта, удаляя все следы "Windows"
ЗапуститьПриложение("dos2unix '" + ФайлСкрипта + "'",, Истина);

// Формируем команды и выполняем с указанным таймаутом в секундах
КомандаЗапускаСкрипта = "timeout " + XMLСтрока(ТаймаутВыполненияСек) + "s /bin/bash '" 
	+ ФайлСкрипта + "' >> '" + ФайлРезультатСкрипта + "'";	
КодВозврата = Неопределено;
ЗапуститьПриложение(КомандаЗапускаСкрипта, , Истина, КодВозврата);

// Получаем результатирующий вывод приложения
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ФайлРезультатСкрипта, КодировкаТекста.UTF8);
РезультатВыполнения = ТекстовыйДокумент.ПолучитьТекст();

// Очистка данных
УдалитьФайлЕслиВозможно(ФайлСкрипта);
УдалитьФайлЕслиВозможно(ФайлРезультатСкрипта);

// Обработка результата выполнения	
Если НЕ КодВозврата = 0 Тогда
	ВызватьИсключение "Не удалось выполнить команду. Код возврата: " + КодВозврата;
КонецЕсли;

Здесь мы устанавливаем произвольный текст команды для Bash и выполняем его. В чем то прием аналогичен тому, что мы делали для Windows. Комментарии даны полные, но на паре моментов остановимся подробнее.

Некоторые нюансы

Первое, что может показаться интересным - это вызов "dos2unix" для сформированного ранее файла скрипта. Зачем это нужно? В операционной системе Windows по умолчанию для переноса строк в файлах используется последовательность символов "\r\n" (перевод каретки + перенос строки). В Unix-подобных системах используется только символ переноса строки "\n". Для Windows символ перевода каретки был добавлен для того, чтобы в древние времена можно было отправлять на печать текст без каких-либо особых драйверов. Телетайп навсегда! Этот легаси остался и по сей день и никому не мешает, ну почти.

Нам же он может сильно помешать по двум причинам:

  1. Несмотря на то, что сервер 1С установлен под Linux - все равно стандартный перенос строки платформа формирует как "\r\n". Даже если для таких классов как "ЗаписьТекста" или "ТекстовыйДокумент" устанавливать символ переноса строки другой (например, Симполв.ПС или по коду символа переноса строки равному 10), то платформа все равно использует символ перевода каретки.
  2. Еще может быть ситуация, когда текст команды для выполнения передается с клиента под управлением Windows на сервер под Linux и символы перевода каретки будут там присутствовать.

Мешать они будут потому что Bash не понимает что с ними делать. Если в файле скрипта будет содержаться символ "\r", то мы получим ошибку:

$'\r': command not found

Вот, например, обсуждение подобной проблемы. Так вот, с помощью команды "dos2unix" можно убрать все символы, несовместимые содержимым скрипта Bash и сделать его корректным. На скриншоте ниже показан пример преобразования содержимого скрипта. (Да, я использую Notepad++ даже в Linux, если Вы его узнали).

Конечно, тут есть минус - пакет "dos2unix" должен быть установлен на сервер. Сделать это проще простого. Вот так это, например, выглядит для Ubuntu:

sudo apt install dos2unix

Но это не единственная особенность. Для того, чтобы ограничить время выполнения команды мы используем штатные возможности - команду timeout. С ее помощью мы можем указать сколько времени выделяется для выполнения команды / скрипта.

timeout 10s bash 'путь к файлу скрипта или команда'

В примере выше мы выполняем некоторый скрипт с таймаутом 10 секунд. Подробнее смотрите мануал :)

Теперь Вы можете запускать приложения, скрипты или команды с помощью Bash из Linux безопасным способом.

Скрытая угроза

Частным случаем запуска процессов небезопасным образом является использование COM-объектов. Не все COM-объекты порождают процессы, которые нужно контролировать. Но, например, всеми любимые Word и Excel, которые часто до сих пор ставят на сервера, делают именно так. Они запускают соответствующий процесс "word.exe" или "excel.exe" и дальше управляют им. Не говоря уже про чистоту использования лицензий (эта тема касалась здесь), это еще и не всегда безопасно с точки зрения работы этих приложений.

Процедура СоздатьИЗаполнитьДокумент(ПутьКШаблону)
 
    ПриложениеWord = Новый COMОбъект("Word.Application");
    ОбъектДокумента = ПриложениеWord.Documents.Add(ПутьКШаблону);
 
    // ... тут какие-то действия по заполнению и сохранению ...

    // Закрываем приложение
    ОбъектДокумента.Application.Quit();
  
КонецПроцедуры

Тут все просто - в момент создания объекта документа для его обработки как-раз и создается процесс "word.exe". После завершения всех необходимых действий, метод "Quit" закрывает приложение и все работает как надо. Но что, если в момент выполнения алгоритма заполнения произойдет ошибка? Правильно, метод "Quit" не будет выполнен и процесс Word'а останется "висеть". Конечно, можно попытаться обезопасить себя как это рекомендует стандарт разработки 1С и добавить "попытку":

Процедура СоздатьИЗаполнитьДокумент(ПутьКШаблону)
 
    ПриложениеWord = Неопределено;
    ОбъектДокумента = Неопределено;

    Попытка
        ПриложениеWord = Новый COMОбъект("Word.Application");
        ОбъектДокумента = ПриложениеWord.Documents.Add(ПутьКШаблону);
    
        // ... тут какие-то действия по заполнению и сохранению ...

        // Закрываем приложение
        ОбъектДокумента.Application.Quit();
    Исключение
        
        Попытка
            ОбъектДокумента.Application.Quit();
            ОбъектДокумента = Неопределено;
        Исключение
            ОбъектДокумента = Неопределено;
        КонецПопытки;
        ПриложениеWord = Неопределено;        

    КонецПопытки;
  
КонецПроцедуры

Тут мы пытаемся закрыть приложение и освободить все связанные ресурсы. Часть кейсов это решит, но, к сожалению, не все. Если, например, в момент работы с COM-объектом возникнет не исключение, а падение рабочего процесса, то никакие действия по освобождению ресурсов выполнены не будут и процесс останется висеть в памяти до перезагрузки сервера / компьютера. Ну или пока не будет "убит" принудительно.

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

А у Вас на сервере бывают ситуации с десятком запущенный процессов "excel.exe"? :)

Альтернативные подходы

В качестве многоточия для этой темы хотел бы упомянуть и альтернативные способы решения проблем с освобождением ресурсов запущенных из 1С процессов:

  • Организовать bat/ps/bash скрипт, который будет ночью "убивать" определенные процессы. Например, те же "excel.exe". Костыль? Да. Работает? Да.
  • Сохранять в базе 1С (например, в регистре сведений) информацию о запущенных процессах (идентификатор процесса, имя и др.). Ночью или в другое время запускать регл. задание, которое будет проверять завершение этих процессов. Костыль? Да. Работает? Да.
  • Перезагружать сервер с периодичностью в несколько дней. О сколько проблем можно решить! :) Костыль? Да. Работает? Да :)))

Список можно продолжать и дальше. Но возможно правильным вариантом будет - поиск решения задач иным способом, а не запуском сторонних процессов. Если такое, конечно, возможно.

Удачи, друзья!

Всем чистого кода, хороших решений и меньше "костылей"! До следующих встреч!

А как Вы работаете со сторонними процессами из 1С?

Другие ссылки

Авторские разработки

 
 Другие разработки

 

Приложение запуск безопасный код COM shell

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    4532    dsdred    53    

72

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    5295    YA_418728146    25    

63

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6410    dsdred    36    

112

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    18475    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    12088    human_new    27    

74

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8822    YA_418728146    6    

141

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6279    sebekerga    54    

94

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15986    SeiOkami    31    

103
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ivanov660 4330 21.07.20 09:56 Сейчас в теме
Думаю, что для части случаев будет удобнее и прозрачнее использовать компоненту на NativeAPI в качестве обертки. Даже где-то тут на сайте подобное решение было представлено публике (в части запуска/управления приложениями).
4. пользователь 21.07.20 10:17
(1) трудно сказать, посмотреть бы на эти компоненты. Ну и если в компоненте пойдет что-то не так, то нужно постараться это все диагностировать.

Но от варианта не отказываюсь :)
2. МимохожийОднако 141 21.07.20 10:16 Сейчас в теме
ОФФ. На картинке и в заголовке немного разные по смыслу утверждения ))
3. пользователь 21.07.20 10:17
(2) Вы заметили тонкий намек )))))
МимохожийОднако; +1 Ответить
12. ishelper 21.07.20 14:13 Сейчас в теме
(3)
Вы заметили тонкий намек )))))
"Альтернативные походы" - это тоже тонкий намек?
YPermitin; +1 Ответить
13. пользователь 21.07.20 14:14
(12) скорее это уже тонкий намек на мою невнимательность :)))
16. пользователь 21.07.20 20:39
5. starik-2005 3033 21.07.20 12:23 Сейчас в теме
ТекстовыйДокумент.РазделительСтрок("ВК");
BaphoBush; Fox-trot; +2 Ответить
6. пользователь 21.07.20 12:34
(5)

ОбщегоНазначенияКлиентСервер.СообщитьПользователю("?");
7. starik-2005 3033 21.07.20 12:35 Сейчас в теме
8. пользователь 21.07.20 12:36
9. starik-2005 3033 21.07.20 12:37 Сейчас в теме
10. zqzq 23 21.07.20 14:07 Сейчас в теме
(5)
ТекстовыйДокумент.РазделительСтрок (TextDocument.LineSeparator)
ТекстовыйДокумент (TextDocument)
РазделительСтрок (LineSeparator)
Использование:

Чтение и запись.
Описание:

Тип: Строка.
Определяет разделитель строк. Может принимать только следующие значения: ВК, ПС или ВК+ПС.
При попытке установки других значений будет инициировано исключение.

Доступность:

Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение.
Примечание:

Значение по умолчанию ПС.
Показать
Тогда нужно вызывать
ТекстовыйДокумент.РазделительСтрок(Символы.ВК)
11. пользователь 21.07.20 14:10
(10) да это не поможет в тех случаях, когда с клиента Windows строкой передается текст скрипта и записывается в этот текстовый документ, там символ перевода каретки сохраняется.

Хочу попробовать средствами 1С удалить символ \r с помощью потоков, то это когда доберусь до обработки интерпретатора, буду новую версию делать.
14. Altez 256 21.07.20 19:20 Сейчас в теме
(11) Через чтение/запись двоичных данных нормально удаляется
YPermitin; +1 Ответить
15. пользователь 21.07.20 19:25
(14) я на это надеялся:)

А есть пример кода для этого дела?
17. Altez 256 21.07.20 21:01 Сейчас в теме
(15) Только 3 буквы про обрезание конца файла под рукой. Но по смыслу можно через Буфер.Получить(<Позиция>) побайтовым сравнением найти <CR>
потом
Буфер.ПолучитьСрез(<Позиция>, <Количество байт до <CR>>)
и
ЗаписатьБуферДвоичныхДанных(Буфер);

	ДвоичныеДанные = Новый ДвоичныеДанные(ФайлПолноеИмя);
	Сообщить("Размер файла: "+ДвоичныеДанные.Размер()+" байт, перезаписываем без финального конца строки(ODOAh)");   
	ЧтениеДанных = Новый ЧтениеДанных(ДвоичныеДанные,, ПорядокБайтов.BigEndian);
	Буфер = ЧтениеДанных.ПрочитатьВБуферДвоичныхДанных(РазмерФайла-2);
	ЧтениеДанных.Закрыть();
	ДвоичныеДанные=Неопределено;
	УдалитьФайлы(ФайлПолноеИмя);
	ЗаписьДанных = Новый ЗаписьДанных(ФайлПолноеИмя);
	ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(Буфер);
	ЗаписьДанных.Закрыть();
Показать
YPermitin; +1 Ответить
18. пользователь 22.07.20 07:08
(17) спасибо!

Поэксперементирую.
19. markers 274 22.07.20 07:53 Сейчас в теме
Я извиняюсь, но почему нельзя обойтись без dos2unix этим способом?
ПереносСтроки = Символы.ПС;
ЗаписьТекста = Новый ЗаписьТекста(ФайлСкрипта, КодировкаТекста.UTF8, ПереносСтроки);
ТекстСкрипта = "#!/bin/sh
	|
	|" + ТекстКомандыДляВыполнения + "
	|";

ЗаписьТекста.Записать(СтрЗаменить(ТекстСкрипта, Символы.ВК + Символы.ПС, Символы.ПС));
ЗаписьТекста.Закрыть();
Показать

Или вы хотите сказать, что 1С ЗаписьТекста, использует не указанный символ переноса, а всё-равно добавляет возврат каретки?
YPermitin; +1 Ответить
20. пользователь 22.07.20 08:05
(19) я, честно, пробовал так сделать, но в файл все равно попадают символы переноса каретки.
Плюс если клиент Windows отправит текст команды на сервер Linux, то там тоже есть символ переноса каретки.

Выше я написал, что надо как-то удалить символ \r через потоки, например. Пока этим просто не занимался.
21. markers 274 22.07.20 08:08 Сейчас в теме
(20) Ну так мой код удалит \r и в команде полученной от куда бы то ни было. Даже в моем примере используется | которая по факту вставляет как вы говорите \r\n.
Мне к сожалению не где проверить, если кто может, проверьте, будет интересно.
22. пользователь 22.07.20 08:09
(21) сейчас попробую :)
23. пользователь 22.07.20 08:17
(22) вот что получилось (см. скриншот).

Платформа настойчиво использует символ \r.

Код заменил на тот что выше.
// Подготавливаем файл скрипта
	ПереносСтроки = Символы.ПС;
	ЗаписьТекста = Новый ЗаписьТекста(ФайлСкрипта, КодировкаТекста.UTF8, ПереносСтроки);
	ТекстСкрипта = "#!/bin/sh
	|
	|" + ТекстКомандыДляВыполнения + "
	|";
	
	ЗаписьТекста.Записать(СтрЗаменить(ТекстСкрипта, Символы.ВК + Символы.ПС, Символы.ПС));
	ЗаписьТекста.Закрыть();
	//ПереносСтроки = Символы.ПС;
	//ЗаписьТекста = Новый ЗаписьТекста(ФайлСкрипта, КодировкаТекста.UTF8, ПереносСтроки);
	//ЗаписьТекста.ЗаписатьСтроку("#!/bin/sh");
	//ЗаписьТекста.ЗаписатьСтроку("");
	//ЗаписьТекста.Записать(ТекстКомандыДляВыполнения);
	//ЗаписьТекста.ЗаписатьСтроку("");
	//ЗаписьТекста.Закрыть();
Показать


У меня возникла мысль, что возможно это "фича" платформы.
В том плане, что я открываю конфигуратор и клиентское приложение на ОС Windows, а сервер под Linux.
И даже то, что я отлаживаю серверный код под Windows может влияет на используемые символы переноса строк в тексте?

В общем, надо еще ковырять. Но замену костылю dos2unix я в любом случае найду, просто позже.
Прикрепленные файлы:
24. markers 274 22.07.20 08:42 Сейчас в теме
(23) хм. спасибо за проверку. возможно есть и косяк платформы, которая стараясь уравнять условия работы в винде и линуксе, в данном случае делает косяк.
YPermitin; +1 Ответить
25. пользователь 22.07.20 08:44
(24) еще одна загадка. Повод для новой статьи :))))
26. Altez 256 22.07.20 13:58 Сейчас в теме
(24) Это не платформы скорее косяк , а низкоуровневых библиотек. В си встречается такая же проблема с записью текста. Пруфа нет, респект тому, кто достанет и разложит по понятиям.
27. Yashazz 4709 22.07.20 17:15 Сейчас в теме
Ну вот. Хотел позлобствовать, наехать, а тут такая хорошая публикация. Разве что заглавная картинка совершенно не подходит к содержанию, но такое некоторым на ИС можно выкладывать.
28. German 413 24.07.20 15:31 Сейчас в теме
В PowerShell лишнее
"  > """ + ВременныйФайлРезультат + """

а как сделать окно в свернутом виде?
YPermitin; +1 Ответить
29. пользователь 24.07.20 15:59
(28)
В PowerShell лишнее


В данном случае да. Можно результат выполнения в файл не сохранять.

а как сделать окно в свернутом виде?


Вместо Exec можно использовать Run, но тогда есть риск, что приложение "зависнет" и потом приложения будет ожидать бесконечно.
Я так понимаю, что при выполнении на клиенте появляется такое окно.

Гарантированного способа скрыть консоль не искал, разве что выполнять команду Run и каким-то другим образом проверять не зависнет ли.
Либо ... делать внешнюю компоненту для таких дел.
Но может есть и проще способ.
30. DO_WHILE_LOOP 358 25.09.20 21:44 Сейчас в теме
Пример скрытия консольного окна (для windows) можно посмотреть здесь
используется утилита hidec.exe обсуждение и исходники утилиты
31. Malfarion 251 02.08.21 00:53 Сейчас в теме
&НаКлиентеНаСервереБезКонтекста
функция ЗаписатьФайлВформатеUTF8безBOM(текст,полноеИмяФайла)

    // записываем в файл с символами BOM в начале файле	
    ТекстовыйФайлUTF8_Bom = Новый ТекстовыйДокумент();
    ТекстовыйФайлUTF8_Bom.ДобавитьСтроку(текст);
    ТекстовыйФайлUTF8_Bom.Записать(полноеИмяФайла,"UTF-8");
	
    // открываем файл и считываем символы после символов BOM
    Данные = Новый ДвоичныеДанные(полноеИмяФайла);
    Строка64=Base64Строка(Данные);
    Строка64=Прав(Строка64,СтрДлина(Строка64)-4);
    ДанныеНаЗапись=Base64Значение(Строка64);
    ДанныеНаЗапись.Записать(полноеИмяФайла); // записываем
	
КонецФункции
Показать


Открываю конкурс на самый простой способ избавиться от BOM =)

//Пояснение, у УстановитьТелоИзСтроки есть 3й параметр ИспользованиеByteOrderMark, по можно его явно поставить в ЛОЖЬ, но судя по доке значение по умолчанию "Авто" для этого параметра для кодировки UTF-8 принимает значение "Не использовать" , по этому экономим лишние символы =) 
&НаКлиентеНаСервереБезКонтекста
функция ЗаписатьФайлВформатеUTF8безBOM(текст,полноеИмяФайла)

  	Запрос=Новый HTTPЗапрос();
	Запрос.УстановитьТелоИзСтроки(текст,КодировкаТекста.UTF8);
	ДвоичныеДанные=Запрос.ПолучитьТелоКакДвоичныеДанные();
	ДвоичныеДанные.Записать(полноеИмяФайла);

	
КонецФункции
Показать
antonio_i; +1 Ответить
32. yurowski 33 11.05.22 11:33 Сейчас в теме
У меня выдает ошибку 127 при попытке запуска приложения

КомандаЗапускаСкрипта = timeout 10s /bin/bash '/tmp/v8_7UBmWF_11.sh' >> '/tmp/v8_7UBmWF_12.log'


127 - "команда не найдена" (Проблема связана либо с переменной окружения $PATH, либо с неверным написанием имени команды)

Не знаете в чем может быть дело?
33. user1129453 23.06.23 04:56 Сейчас в теме
Спасибо! Отличная статья. Подскажите а как можно запускать скрипт с правами администратора?
34. sandr13 32 20.10.23 09:42 Сейчас в теме
Лучшая статья для понимания материала! Плюсую.
35. user983240 16.02.24 12:59 Сейчас в теме
Ничего не работает, код при исполнении зависает и не отпускает
Оставьте свое сообщение