Перейти к содержанию

Евгений Корепов

Пользователи
  • Активность

    718
  • Зарегистрирован

  • Посещение

  • Победитель дней

    90

Евгений Корепов стал победителем дня 26 марта

Евгений Корепов имел наиболее популярный контент!

1 Подписчик

Информация о Евгений Корепов

  • Звание
    Продвинутый пользователь
  • День рождения 22 июля

Информация

  • Пол
    Мужчина
  • Город
    Ухта

Посетители профиля

5 994 просмотров профиля
  1. Класс для работы с FastCGI серверами, такими как php-fpm. Для тех кто не в теме : веб-сервер, к примеру nginx, получает запросы и отправляет их на исполнение FastCGI серверу, к примеру php-fpm, php-fpm получает имя скрипта, параметры, выполняет все и возвращает результат в nginx, который в свою очередь возвращает этот результат запросившему клиенту. С помощью класса вы можете так же, выполнять php скрипты на локальном или удаленном сервере. Исходники https://github.com/EvgeniyKorepov/FastCGIClient Пример delphi var FFastCGI : TFastCGI; ... procedure TFormMain.FormCreate(Sender: TObject); var AHost : String; APort : Word; AScriptFileName, ARequest, AContent : String; begin AHost := '10.0.0.4'; APort := 9000; FFastCGI := TFastCGI.Create(AHost, APort); FFastCGI.KeepAlive := True; AScriptFileName := '/opt/xxx.php'; ARequest := 'request=1234567890'; if FFastCGI.Get(AScriptFileName, ARequest, AContent) then Memo.Text := AContent else Memo.Text := FFastCGI.StatusCode.ToString + ' ' + FFastCGI.StatusText; end; пример php <?php header('Content-Type: text/html; charset=utf-8'); if (isset($_REQUEST["request"])) if ($_REQUEST["request"] == "1234567890") { header("Status: 200"); echo 'OK'; } else { http_response_code(400); echo "ERROR"; }
  2. В прошлой теме я показал как делать демонов старой школы - серьезных и самодостаточных. Но это все в прошлом. Теперь существуют системы управления процессами, где все намного, намного проще. Исходники тут https://github.com/EvgeniyKorepov/LinuxDaemonNewStyle Заметьте, теперь никаких потоков, все элементарно, systemd сделает всю работу за нас. Половина кода - разбор параметров командной строки. Вторая половина - бесконечный цикл, ожидающий сигналов от экземпляра класса демона нового стиля . Код самого класса сократился на треть. Если запустите приложения в консоли - будет самое обычное приложение, которые умрет при закрытии консоли. Запуск в качестве бессмертного демона - через systemd, причем он сможет автоматически перезапускать вашего демона при крахе. Эти параметры задаются в текстовом файле /etc/systemd/system/DaemonNewStyleTest.service program DaemonNewStyleTest; {$APPTYPE CONSOLE} uses System.SysUtils, System.IOUtils, System.SyncObjs, Posix.Stdlib, Posix.SysStat, Posix.SysTypes, Posix.Unistd, Posix.Signal, Posix.Fcntl, Posix.Syslog in 'Posix.Syslog.pas', UnitDaemonNewStyle in 'UnitDaemonNewStyle.pas'; var AEvent : TEventType; begin if ParamCount = 0 then begin syslog(LOG_ERR, 'No parameters'); ExitCode := EXIT_FAILURE; exit; end; if ParamStr(1).ToLower.Equals('stop') then begin if Daemon.Stop(30) then ExitCode := EXIT_SUCCESS else ExitCode := EXIT_FAILURE; exit; end; if ParamStr(1).ToLower.Equals('reload') then begin if Daemon.Reload() then ExitCode := EXIT_SUCCESS else ExitCode := EXIT_FAILURE; exit; end; if not ParamStr(1).ToLower.Equals('start') then begin syslog(LOG_ERR, 'Unknow parameters'); ExitCode := EXIT_FAILURE; exit; end; syslog(LOG_NOTICE, 'main START'); while Daemon.IsRunning do begin syslog(LOG_NOTICE, 'main LOOP'); Daemon.Execute(AEvent); if AEvent <> TEventType.None then syslog(LOG_NOTICE, 'main Daemon receive signal'); case AEvent of TEventType.Start : begin syslog(LOG_NOTICE, 'main Event START'); end; TEventType.Reload : begin // Reload config syslog(LOG_NOTICE, 'main Event RELOAD'); end; TEventType.Stop : begin syslog(LOG_NOTICE, 'main Event STOP'); ExitCode := EXIT_SUCCESS; Sleep(10); // simulate destroy delay break; end; end; Sleep(1000); end; end. systemctl start DaemonNewStyleTest.service systemctl reload DaemonNewStyleTest.service systemctl stop DaemonNewStyleTest.service
  3. У меня в досягаемости только CentOS 7, ну еще Дебиан есть на паре старых серваков. Под ними все работает превосходно. Тут надо под отладкой запускать и смотреть что происходит. Ну и логи системы смотреть
  4. Сначала пишем серверную часть - загрузка сохранения файла на любимом языке. Потом тестируем серверную часть - бросаем на сервер страничку с формой загрузки. Убеждаемся что все работает в браузере. И только после этого пишем клиента...
  5. Вам проще адаптировать сайт https://gector-spb.ru/ для мобильных браузеров. Наймите верстальшика за доширак - обойдется дешевле и по времени гораздо быстрее.
  6. Я написал класс для демонизации приложения в linux. Класс форкает процесс, обрабатывает поступающие сигналы и передает их в основной поток через потокобезопасную очередь. Исходники https://github.com/EvgeniyKorepov/LinuxDaemon Для использования просто подключите модуль UnitDaemon в свое консольное приложение: program DaemonTest; {$APPTYPE CONSOLE} uses System.SysUtils, System.IOUtils, System.SyncObjs, Posix.Stdlib, Posix.SysStat, Posix.SysTypes, Posix.Unistd, Posix.Signal, Posix.Fcntl, Posix.Syslog in 'Posix.Syslog.pas', UnitDaemon in 'UnitDaemon.pas'; var AEventType : TEventType; begin syslog(LOG_NOTICE, 'main START'); while True do begin syslog(LOG_NOTICE, 'main LOOP'); if UnitDaemon.QueueEvent.PopItem(AEventType) = System.SyncObjs.TWaitResult.wrSignaled then begin syslog(LOG_NOTICE, 'main UnitDaemon.QueueEvent.PopItem'); case AEventType of TEventType.StopProcess : begin syslog(LOG_NOTICE, 'main Event StopProcess'); ExitCode := EXIT_SUCCESS; exit; end; TEventType.Start : begin syslog(LOG_NOTICE, 'main Event START'); end; TEventType.Reload : begin // Reload config syslog(LOG_NOTICE, 'main Event RELOAD'); end; TEventType.Stop : begin syslog(LOG_NOTICE, 'main Event STOP'); ExitCode := EXIT_SUCCESS; exit; end; end; end; Sleep(50); end; end. Так же поддерживается systemd - для этого положите DaemonTest.service в /etc/systemd/system/ и используйте : systemctl start DaemonTest.service systemctl reload DaemonTest.service systemctl stop DaemonTest.service
  7. Вот просто идеальная статья по запуску демона под Linux http://blog.paolorossi.net/2017/09/04/building-a-real-linux-daemon-with-delphi-part-2/ Помимо объяснения механизма fork с отличными примерами, есть куча дополнительной наиполезнейшей инфы.
  8. И еще вариант похожий, источник https://stackoverflow.com/questions/44415054/execute-external-program-from-linux-delphi-10-2-console-application uses ... System.SysUtils, Posix.Base, Posix.Fcntl, ...; type TStreamHandle = pointer; function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl; external libc name _PU + 'popen'; function pclose(filehandle: TStreamHandle): int32; cdecl; external libc name _PU + 'pclose'; function fgets(buffer: pointer; size: int32; Stream: TStreamHandle): pointer; cdecl; external libc name _PU + 'fgets'; function runCommand(const acommand: MarshaledAString): String; // run a linux shell command and return output // Adapted from http://chapmanworld.com/2017/04/06/calling-linux-commands-from-delphi/ var handle: TStreamHandle; data: array [0 .. 511] of uint8; function bufferToString(buffer: pointer; maxSize: uint32): string; var cursor: ^uint8; endOfBuffer: nativeuint; begin if not assigned(buffer) then exit; cursor := buffer; endOfBuffer := nativeuint(cursor) + maxSize; while (nativeuint(cursor) < endOfBuffer) and (cursor^ <> 0) do begin result := result + chr(cursor^); cursor := pointer(succ(nativeuint(cursor))); end; end; begin result := ''; handle := popen(acommand, 'r'); try while fgets(@data[0], sizeof(data), handle) <> nil do begin result := result + bufferToString(@data[0], sizeof(data)); end; finally pclose(handle); end; end; function createQRCode(id, fn: string): string; // Create qr-code using qrencode package begin deletefile(fn); if fileExists(fn) then raise Exception.create('Old file not deleted!'); // I am targeting rhel for now, so I know the path for sure result := runCommand(MarshaledAString(UTF8STring('/usr/bin/qrencode -o ' + fn + ' ''' + id + ''''))); if not fileExists(fn) then raise Exception.create('New file not created!'); end; function testqr: String; // Test QR Code creation with error handling // QREncode does not output anything but who knows ;-) begin try result := createQRCode('08154711', '/tmp/myqrcode.png'); except on e: Exception do begin result := 'Error: ' + e.message; end; end; end;
  9. Отсюда https://chapmanworld.com/2017/04/06/calling-linux-commands-from-delphi/ program myls; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Posix.Base, Posix.Fcntl; type TStreamHandle = pointer; /// <summary> /// Man Page: http://man7.org/linux/man-pages/man3/popen.3.html /// </summary> function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl; external libc name _PU + 'popen'; /// <summary> /// Man Page: http://man7.org/linux/man-pages/man3/pclose.3p.html /// </summary> function pclose(filehandle: TStreamHandle): int32; cdecl; external libc name _PU + 'pclose'; /// <summary> /// Man Page: http://man7.org/linux/man-pages/man3/fgets.3p.html /// </summary> function fgets(buffer: pointer; size: int32; Stream: TStreamHAndle): pointer; cdecl; external libc name _PU + 'fgets'; /// <summary> /// Utility function to return a buffer of ASCII-Z data as a string. /// </summary> function BufferToString( Buffer: pointer; MaxSize: uint32 ): string; var cursor: ^uint8; EndOfBuffer: nativeuint; begin Result := ''; if not assigned(Buffer) then begin exit; end; cursor := Buffer; EndOfBuffer := NativeUint(cursor) + MaxSize; while (NativeUint(cursor)<EndOfBuffer) and (cursor^<>0) do begin Result := Result + chr(cursor^); cursor := pointer( succ(NativeUInt(cursor)) ); end; end; var Handle: TStreamHandle; Data: array[0..511] of uint8; begin try Handle := popen('/bin/ls -lart','r'); try while fgets(@data[0],Sizeof(Data),Handle)<>nil do begin Write(BufferToString(@Data[0],sizeof(Data))); end; finally pclose(Handle); end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
  10. А вот я и не прав! Теперь я тоже проклят и напоролся на точно такую же проблему. Действительно, PopItem в непредсказуемый момент изменяет поведение - любой таймаут (от 1 до INFINITE) превращается в 0. И похоже проблеме уже 2 года, но Эмбаркадера делает вид что в " я в домике". Т.е. полностью игнорирует проблему. Дело похоже как обычно в злощастном TMonitor - то одна проблема, то другая, то опять внедряют предыдущую проблему. Вот найденные ссылки по этой проблеме: https://forums.embarcadero.com/thread.jspa?messageID=941762 https://quality.embarcadero.com/browse/RSP-19993 А вот тут речь тоже о той же самой проблеме, дата 2012 год https://delphihaven.wordpress.com/2012/01/30/fixing-tthreadedqueue-or-in-other-words-tmonitor-again/
  11. Вам нужно провести чистый эксперимент на простом приложении и простых условиях. И не использовать Double для условий - лучше использовать целочисленные переменные, чтоб быть уверенным в отсутствии накопления ошибки. Еще важный момент - создание очереди TThreadedQueue<TBytes>.Create(100, 1, 1) не совсем корректно. Вы ставите одинаковый и минимально возможный таймаут на pop и push, и рискуете словить взаимную блокировку. Пока идет push невозможен pop, и наоборот. Обычно, в зависимости от условий, ставят одно гораздо больше другого, к примеру если важна целостность подаваемых данных, то push 1000, а если нужен быстрый поток (который параллельно делает что то еще), то pop 10. Или если поток только обрабатывает входящие данные, то pop 3600 * 24, чтоб он зря не крутился без данных ))) Сейчас у меня приложение на Delphi 10.3.3 крутится месяц без остановки, архитектура - Основной поток -> Поток получения данных -> Поток обработки данных -> 100-200 потоков исполнителей. Весь обмен на очередях. Плюс поток логов и поток мониторинга (они получают данные, каждый по своей очереди, со всех потоков. И никаких аномалий я не заметил, все работает как часы.
  12. Вы создайте запрос прямо на первоисточнике https://github.com/zxing/zxing/issues - автор вам быстрее поможет. Прошу прощения, не туда ссылку дал ) Вот правильная https://github.com/Spelt/ZXing.Delphi/issues
  13. Поиск в форуме совсем тухлый. Пытался найти "чат" - ни одного результата. Спасибо гуглю, поиск по "fire-monkey чат" показал нужные темы.
×
×
  • Создать...