From dcdcd3e8fc05ef0a586f56ba80db490a796fa2f0 Mon Sep 17 00:00:00 2001 From: luciferWei Date: Mon, 12 May 2025 15:20:30 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Feat=EF=BC=9A=E5=A2=9E=E5=8A=A0=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E5=BD=95=E5=88=B6=E5=8A=9F=E8=83=BD=20=20\nSigned-off?= =?UTF-8?q?-by:=20LuciferWei=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BUILD.gn | 1 + src/common/base.cpp | 416 +++++++++++++++++++++++++++++++-- src/common/base.h | 22 +- src/common/define.h | 11 + src/common/server_cmd_log.cpp | 82 +++++++ src/common/server_cmd_log.h | 41 ++++ src/host/server.cpp | 11 + src/host/server.h | 3 +- src/host/server_for_client.cpp | 9 +- src/host/translate.cpp | 4 + 10 files changed, 564 insertions(+), 36 deletions(-) create mode 100644 src/common/server_cmd_log.cpp create mode 100644 src/common/server_cmd_log.h mode change 100755 => 100644 src/host/server.h mode change 100755 => 100644 src/host/server_for_client.cpp mode change 100755 => 100644 src/host/translate.cpp diff --git a/BUILD.gn b/BUILD.gn index d381f6a6..c7a5566e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -38,6 +38,7 @@ hdc_common_sources = [ "src/common/forward.cpp", "src/common/header.cpp", "src/common/heartbeat.cpp", + "src/common/server_cmd_log.cpp", "src/common/session.cpp", "src/common/task.cpp", "src/common/tcp.cpp", diff --git a/src/common/base.cpp b/src/common/base.cpp index 57d08592..e866d542 100644 --- a/src/common/base.cpp +++ b/src/common/base.cpp @@ -41,6 +41,7 @@ #include #endif #include +#include "server_cmd_log.h" using namespace std::chrono; namespace Hdc { @@ -50,6 +51,10 @@ namespace Base { uint16_t g_logFileCount = MAX_LOG_FILE_COUNT; bool g_heartbeatSwitch = true; constexpr int DEF_FILE_PERMISSION = 0750; + bool g_cmdlogSwitch = false; + std::vector g_cmdLogsFilesStrings; + std::mutex g_threadCompressCmdLogsMutex; + std::shared_ptr g_compressCmdLogsThread; uint8_t GetLogLevel() { return g_logLevel; @@ -146,6 +151,29 @@ namespace Base { } } + bool CompareLogFileName(const string &a, const string &b) + { + return strcmp(a.c_str(), b.c_str()) > 0; + } + + void GetTimeString(string &timeString) + { + system_clock::time_point timeNow = system_clock::now(); + system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 + time_t sinceUnix0Time = duration_cast(sinceUnix0).count(); + std::tm *timeTm = std::localtime(&sinceUnix0Time); + + const auto sinceUnix0Rest = duration_cast(sinceUnix0).count() % TIME_BASE; + string msTimeSurplus = StringFormat("%03llu", sinceUnix0Rest); + timeString = msTimeSurplus; + if (timeTm != nullptr) { + char buffer[TIME_BUF_SIZE] = {0}; + if (strftime(buffer, TIME_BUF_SIZE, "%Y%m%d-%H%M%S", timeTm) > 0) { + timeString = StringFormat("%s%s", buffer, msTimeSurplus.c_str()); + } + } + } + #ifndef HDC_HILOG void LogToPath(const char *path, const char *str) { @@ -183,29 +211,6 @@ namespace Base { #endif } - void GetTimeString(string &timeString) - { - system_clock::time_point timeNow = system_clock::now(); - system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 - time_t sinceUnix0Time = duration_cast(sinceUnix0).count(); - std::tm *timeTm = std::localtime(&sinceUnix0Time); - - const auto sinceUnix0Rest = duration_cast(sinceUnix0).count() % TIME_BASE; - string msTimeSurplus = StringFormat("%03llu", sinceUnix0Rest); - timeString = msTimeSurplus; - if (timeTm != nullptr) { - char buffer[TIME_BUF_SIZE] = {0}; - if (strftime(buffer, TIME_BUF_SIZE, "%Y%m%d-%H%M%S", timeTm) > 0) { - timeString = StringFormat("%s%s", buffer, msTimeSurplus.c_str()); - } - } - } - - bool CompareLogFileName(const string &a, const string &b) - { - return strcmp(a.c_str(), b.c_str()) > 0; - } - bool CreateLogDir() { string errMsg; @@ -2561,6 +2566,7 @@ void CloseOpenFd(void) UpdateLogLimitFileCountCache(); #endif UpdateHeartbeatSwitchCache(); + UpdateCmdLogSwitch(); } const HdcFeatureSet& GetSupportFeature(void) @@ -2629,5 +2635,369 @@ void CloseOpenFd(void) fileStream.close(); return ret; } + void UpdateCmdLogSwitch() + { + char *env = getenv(ENV_SERVER_CMD_LOG.c_str()); + if (!env) { + g_cmdlogSwitch = false; + return; + } + size_t envLen = strlen(env); + if (envLen > 1) { + g_cmdlogSwitch = false; + return; + } + constexpr size_t maxLen = 1; + if (envLen != maxLen) { + g_cmdlogSwitch = false; + return; + } + if (strncmp(env, "1", maxLen) == 0) { + g_cmdlogSwitch = true; + return; + } + g_cmdlogSwitch = false; + } + + bool GetCmdLogSwitch() + { + return g_cmdlogSwitch; + } + + inline std::string GetCmdLogDirName() + { + return GetTmpDir() + CMD_LOG_DIR_NAME + GetPathSep(); + } + + void TimeoutHandler(int signum) + { + WRITE_LOG(LOG_FATAL, "Timeout occurred!"); + exit(1); + } + + #ifdef _WIN32 + // according to *.tgz format compression + bool CompressLogFile(const std::string& filePath, + const std::string& sourceFileName, + const std::string& targetFileName) + { + bool retVal = false; + string sourceFileNameFull = filePath + sourceFileName; + if (access(sourceFileNameFull.c_str(), F_OK) != 0) { + WRITE_LOG(LOG_FATAL, "file %s not exist", sourceFileNameFull.c_str()); + return retVal; + } + if (targetFileName.empty()) { + WRITE_LOG(LOG_FATAL, "file %s is empty", targetFileName.c_str()); + return retVal; + } + char currentDir[BUF_SIZE_DEFAULT] = { 0 }; + getcwd(currentDir, sizeof(currentDir)); + char buf[BUF_SIZE_SMALL] = { 0 }; + if (sprintf_s(buf, sizeof(buf) - 1, "tar czfp %s %s", targetFileName.c_str(), sourceFileName.c_str()) < 0) { + WRITE_LOG(LOG_FATAL, "sprintf_s failed"); + return retVal; + } + chdir(filePath.c_str()); + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + if (!CreateProcess(GetTarBinFile().c_str(), buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + DWORD errorCode = GetLastError(); + LPVOID messageBuffer; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&messageBuffer, 0, NULL); + WRITE_LOG(LOG_FATAL, "compress file failed ,cmd:%s,error:%s", buf, (LPTSTR)messageBuffer); + LocalFree(messageBuffer); + } else { + DWORD waitResult = WaitForSingleObject(pi.hProcess, INFINITE); + if (waitResult == WAIT_OBJECT_0) { + retVal = true; + } else if (waitResult == WAIT_TIMEOUT) { + retVal = true; + } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + chdir(currentDir); + return retVal; + } + #else + bool CompressLogFile(const std::string& filePath, + const std::string& sourceFileName, + const std::string& targetFileName) + { + bool retVal = false; + string sourceFileNameFull = filePath + sourceFileName; + if (access(sourceFileNameFull.c_str(), F_OK) != 0) { + WRITE_LOG(LOG_FATAL, "file %s not exist", sourceFileNameFull.c_str()); + return retVal; + } + if (targetFileName.empty()) { + WRITE_LOG(LOG_FATAL, "file %s is empty", targetFileName.c_str()); + return retVal; + } + char currentDir[BUF_SIZE_DEFAULT] = { 0 }; + getcwd(currentDir, sizeof(currentDir)); + pid_t pc = fork(); // create process + chdir(filePath.c_str()); + if (pc < 0) { + WRITE_LOG(LOG_WARN, "fork subprocess failed"); + } else if (pc == 0) { + signal(SIGALRM, TimeoutHandler); + alarm(MAX_PROCESS_TIMEOUT); + if ((execlp(GetTarToolName().c_str(), + GetTarToolName().c_str(), + GetTarParams().c_str(), + targetFileName.c_str(), + sourceFileName.c_str(), + nullptr)) == -1) { + WRITE_LOG(LOG_WARN, "CompressLogFile execlp failed "); + } + } else { + int status = 0; + waitpid(pc, &status, 0); + if (WIFEXITED(status)) { + int exitCode = WEXITSTATUS(status); + WRITE_LOG(LOG_DEBUG, "subprocess exited withe status: %d", exitCode); + retVal = true; + } else { + WRITE_LOG(LOG_FATAL, "CompressLogFile failed, soiurceFileNameFull:%s, error:%s", + sourceFileNameFull.c_str(), + strerror(errno)); + } + } + chdir(currentDir); + return retVal; + } + #endif + + bool CompressCmdLogAndRemove(const std::string& pathName, + const std::string& fileName, + const std::string& targetFileName) + { + std::string sourceFileName = pathName + fileName; + if (sourceFileName.empty()) { + WRITE_LOG(LOG_FATAL, "file name is empty"); + return false; + } + if (access(sourceFileName.c_str(), F_OK) != 0) { + WRITE_LOG(LOG_FATAL, "path %s not exist", pathName.c_str()); + return false; + } + if (!CompressLogFile(pathName, fileName, targetFileName)) { + WRITE_LOG(LOG_FATAL, "compress %s failed", targetFileName.c_str()); + return false; + } + unlink(sourceFileName.c_str()); + return true; + } + + bool IsFileSizeLessThan(const std::string& fileName, const size_t fileMaxSize) + { + uv_fs_t fs; + int value = uv_fs_stat(nullptr, &fs, fileName.c_str(), nullptr); + uint64_t fileSize = fs.statbuf.st_size; + uv_fs_req_cleanup(&fs); + if (value != 0) { + constexpr int bufSize = 1024; + char buf[bufSize] = { 0 }; + uv_strerror_r(value, buf, bufSize); + WRITE_LOG(LOG_FATAL, "uv_fs_stat failed, file:%s error:%s", fileName.c_str(), buf); + return true; + } + if (fileSize < fileMaxSize) { + return true; + } + return false; + } + + vector GetDirFileNameFromPath(const std::string& path, + const std::string& matchPreStr, + const std::string& matchSufStr) + { + g_cmdLogsFilesStrings.clear(); + #ifdef _WIN32 + WIN32_FIND_DATAA findData; + std::string matchStr = matchPreStr + "*" + matchSufStr; + std::string findFileMatchStr = path + "/" + matchStr; + HANDLE hFind = FindFirstFile(findFileMatchStr.c_str(), &findData); + if (hFind == INVALID_HANDLE_VALUE) { + WRITE_LOG(LOG_FATAL, "FindFirstFile failed, path:%s", findFileMatchStr.c_str()); + return ; + } + do { + if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + SetErrorMode(SEM_FAILCRITICALERRORS); + g_cmdLogsFilesStrings.push_back(findData.cFileName); + } + } while (FindNextFile(hFind, &findData)); + #else + DIR *dir = opendir(path.c_str()); + if (dir == nullptr) { + WRITE_LOG(LOG_WARN, "open %s failed", path.c_str()); + return g_cmdLogsFilesStrings; + } + struct dirent *entry; + while ((entry = readdir(dir)) != nullptr) { + string fileName = entry->d_name; + if ((strncmp(fileName.c_str(), matchPreStr.c_str(), matchPreStr.length()) == 0) && + (strncmp(fileName.c_str() + fileName.length() - matchSufStr.length(), matchSufStr.c_str(), + matchSufStr.length()) == 0)) { + g_cmdLogsFilesStrings.push_back(fileName); + } + } + closedir(dir); + #endif + return g_cmdLogsFilesStrings; + } + + void ControlFilesByRegex(const std::string& path, + const std::string& matchPreStr, + const std::string& matchSufStr, + int maxFiles) + { + vector files = GetDirFileNameFromPath(path, matchPreStr, matchSufStr); + if (files.size() <= static_cast(maxFiles)) { + return; + } + sort(files.begin(), files.end(), CompareLogFileName); + + uint32_t delCount = files.size() - static_cast(maxFiles); + uint32_t beginCount = files.size() - delCount; + for (auto name = files.begin() + beginCount; name != files.end(); name++) { + string delFileName = path.c_str() + *name; + WRITE_LOG(LOG_INFO, "delete file %s", delFileName.c_str()); + unlink(delFileName.c_str()); + } + return; + } + + void ThreadProcessCmdLogs() + { + string path = GetCmdLogDirName(); + string logFileName = path + CMD_LOG_FILE_NAME; + if (IsFileSizeLessThan(logFileName, MAX_COMPRESS_LOG_FILE_SIZE)) { + return; + } + string timeStr; + GetTimeString(timeStr); + string renameFileName = CMD_LOG_COMPRESS_FILE_NAME_PREFIX + timeStr + CMD_LOG_FILE_TYPE; + string renameFilePath = path + renameFileName; + if (rename(logFileName.c_str(), renameFilePath.c_str()) != 0) { + WRITE_LOG(LOG_FATAL, "rename file %s failed", logFileName.c_str()); + } + string targetTarFileName = renameFileName + CMD_LOG_COMPRESS_FILE_NAME_SUFFIX; + if (!CompressCmdLogAndRemove(path, renameFileName, targetTarFileName)) { + WRITE_LOG(LOG_FATAL, "compress and remove file %s failed", renameFileName.c_str()); + return; + } + //delete old files + ControlFilesByRegex(path, + CMD_LOG_COMPRESS_FILE_NAME_PREFIX, + CMD_LOG_COMPRESS_FILE_NAME_SUFFIX, + MAX_COMPRESS_LOG_FILE_COUNT); + } + + void SaveLogToPath(const std::string& path, const std::string& str) + { + int flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND; + uv_fs_t req; + int fd = uv_fs_open(nullptr, &req, path.c_str(), flags, S_IWUSR | S_IRUSR, nullptr); + if (fd < 0) { + char buffer[BUF_SIZE_DEFAULT] = { 0 }; + uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); + uv_fs_req_cleanup(&req); + WRITE_LOG(LOG_FATAL, "SaveLogToPath failed, path:%s error:%s", path.c_str(), buffer); + return; + } + string text(str); + uv_buf_t wbf = uv_buf_init((char *)str.c_str(), text.size()); + uv_fs_req_cleanup(&req); + uv_fs_write(nullptr, &req, fd, &wbf, 1, -1, nullptr); + uv_fs_close(nullptr, &req, fd, nullptr); + } + + bool EnsureDirectoryExists(const std::string& directoryPath) + { + uv_fs_t req; + int result = uv_fs_stat(nullptr, &req, directoryPath.c_str(), nullptr); + if (result == 0) { + return true; + } else if (result == UV_ENOENT) { + uv_fs_req_cleanup(&req); + result = uv_fs_mkdir(nullptr, &req, directoryPath.c_str(), DEF_FILE_PERMISSION, nullptr); + if (result == 0) { + WRITE_LOG(LOG_INFO, "Directory created: %s", directoryPath.c_str()); + return true; + } else { + WRITE_LOG(LOG_FATAL, "Failed to create directory: %s:Error:%d", directoryPath.c_str(), result); + return false; + } + } else { + WRITE_LOG(LOG_FATAL, "Failed to check directory: %s:Error:%d", directoryPath.c_str(), result); + return false; + } + } + + bool SaveCmdLogsToFile() + { + std::string pathNames = GetCmdLogDirName(); + std::string cmdLogFileName = pathNames + CMD_LOG_FILE_NAME; + std::string cmdLog = ""; + if (!EnsureDirectoryExists(pathNames)) { + WRITE_LOG(LOG_FATAL, "EnsureDirectoryExists failed"); + return false; + } + size_t loopCount = 0; + while (Hdc::ServerCmdLog::GetInstance().CmdLogStrSize() != 0) { + if (loopCount > MAX_SAVE_CMD_LOG_TO_FILE_COUNTS) { + break; + } + loopCount++; + cmdLog = Hdc::ServerCmdLog::GetInstance().PopCmdLogStr(); + if (!cmdLog.empty()) { + SaveLogToPath(cmdLogFileName, cmdLog); + } + } + return true; + } + + void ThreadCmdStrAndCmdLogs() + { + bool running = Hdc::ServerCmdLog::GetInstance().GetRunningStatus(); + while (running) { + size_t cmdLogCount = 0; + cmdLogCount = Hdc::ServerCmdLog::GetInstance().CmdLogStrSize(); + auto lastFlushTime = Hdc::ServerCmdLog::GetInstance().GetLastFlushTime(); + size_t compareTime = std::chrono::duration_cast( + std::chrono::system_clock::now() - lastFlushTime).count(); + WRITE_LOG(LOG_INFO, "ThreadCmdStrAndCmdLogs:cmdLogCount%d:compareTime:%d", cmdLogCount, compareTime); + if ((cmdLogCount > MAX_SAVE_CMD_LOG_TO_FILE_COUNTS) || (compareTime > MAX_SAVE_CMD_LOG_TO_FILE_CYCLE)) { + SaveCmdLogsToFile(); + ThreadProcessCmdLogs(); + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + + void ProcessCmdLogs() + { + if (!g_cmdlogSwitch) { + return; + } + std::unique_lock lock(g_threadCompressCmdLogsMutex); + g_compressCmdLogsThread = std::make_shared(ThreadCmdStrAndCmdLogs); + } + + std::string CmdLogStringFormat(uint32_t targetSessionId, const std::string& cmdStr) + { + string timeStr; + GetTimeString(timeStr); + return StringFormat("[%s] %u %s\n", timeStr.c_str(), targetSessionId, cmdStr.c_str()); + } } // namespace Base } // namespace Hdc diff --git a/src/common/base.h b/src/common/base.h index b528b7b9..178e985d 100644 --- a/src/common/base.h +++ b/src/common/base.h @@ -181,6 +181,15 @@ namespace Base { string GetFileNameAny(string &path); string GetCwd(); string GetTmpDir(); + inline string GetTarToolName() + { + return LOG_COMPRESS_TOOL_NAME; + } + inline string GetTarParams() + { + return LOG_COMPRESS_TOOL_PARAMS; + } + void GetTimeString(string &timeString); #ifndef HDC_HILOG void SetLogCache(bool enable); void RemoveLogFile(); @@ -196,10 +205,6 @@ namespace Base { uint32_t GetLogOverCount(vector files, uint64_t limitDirSize); string GetLogDirName(); string GetLogNameWithTime(); - inline string GetTarToolName() - { - return LOG_COMPRESS_TOOL_NAME; - } inline string GetTarBinFile() { #ifdef _WIN32 @@ -208,11 +213,6 @@ namespace Base { return LOG_COMPRESS_TOOL_BIN_UNIX; #endif } - - inline string GetTarParams() - { - return LOG_COMPRESS_TOOL_PARAMS; - } #endif uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp); bool IsRoot(); @@ -293,6 +293,10 @@ namespace Base { void UpdateHeartbeatSwitchCache(); bool GetheartbeatSwitch(); bool WriteToFile(const std::string& fileName, const std::string &content, std::ios_base::openmode mode); + void UpdateCmdLogSwitch(); + bool GetCmdLogSwitch(); + std::string CmdLogStringFormat(uint32_t targetSessionId, const std::string &cmdStr); + void ProcessCmdLogs(); } // namespace base } // namespace Hdc diff --git a/src/common/define.h b/src/common/define.h index a6e7497d..4bd49333 100644 --- a/src/common/define.h +++ b/src/common/define.h @@ -219,5 +219,16 @@ const string TERMINAL_HDC_PROCESS_FAILED = "[E002101]:Terminal hdc process faile char buf[1024] = { 0 }; \ strerror_r(errno, buf, 1024) #endif +const string ENV_SERVER_CMD_LOG = "OHOS_HDC_CMD_RECORD"; +const string CMD_LOG_FILE_NAME = "hdc-cmd.log"; +const string CMD_LOG_DIR_NAME = "hdc_cmd"; +const string CMD_LOG_FILE_TYPE = ".log"; +const string CMD_LOG_COMPRESS_FILE_NAME_PREFIX = "hdc-cmd-"; +const string CMD_LOG_COMPRESS_FILE_NAME_SUFFIX = ".tgz"; +const uint16_t MAX_COMPRESS_LOG_FILE_COUNT = 47; +const uint64_t MAX_COMPRESS_LOG_FILE_SIZE = (50) * 1024 * 1024; // 50MB +const size_t MAX_SAVE_CMD_LOG_TO_FILE_CYCLE = 10; +const size_t MAX_SAVE_CMD_LOG_TO_FILE_COUNTS = 1500; +const size_t MAX_PROCESS_TIMEOUT = 120; // 120 seconds } // namespace Hdc #endif // HDC_DEFINE_H diff --git a/src/common/server_cmd_log.cpp b/src/common/server_cmd_log.cpp new file mode 100644 index 00000000..0749afa6 --- /dev/null +++ b/src/common/server_cmd_log.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "server_cmd_log.h" +#include +#include +#include "log.h" + +namespace Hdc { +ServerCmdLog& ServerCmdLog::GetInstance() +{ + static ServerCmdLog serverCmdLog; + return serverCmdLog; +} + +ServerCmdLog::ServerCmdLog() +{ + lastFlushTime = std::chrono::system_clock::now(); + running_ = true; +} + +ServerCmdLog::~ServerCmdLog() +{ +} + +void ServerCmdLog::PushCmdLogStr(const std::string& cmdLogStr) +{ + constexpr size_t queueSizeMax = 1500; + std::unique_lock lock(pushCmdLogStrRecordMutex); + size_t pushCmdLogStrQueueSize = pushCmdLogStrQueue.size(); + if (pushCmdLogStrQueueSize >= queueSizeMax) { + WRITE_LOG(LOG_INFO, "!!!pushCmdLogStrQueue exceeds threshold:%zu,Do not save CmdLog.", pushCmdLogStrQueueSize); + return; + } + pushCmdLogStrQueue.push(cmdLogStr); +} + +std::string ServerCmdLog::PopCmdLogStr() +{ + std::unique_lock lock(pushCmdLogStrRecordMutex); + if (pushCmdLogStrQueue.empty()) { + return ""; + } + std::string cmdLogStr = pushCmdLogStrQueue.front(); + pushCmdLogStrQueue.pop(); + lastFlushTime = std::chrono::system_clock::now(); + return cmdLogStr; +} + +size_t ServerCmdLog::CmdLogStrSize() +{ + std::unique_lock lock(pushCmdLogStrRecordMutex); + return pushCmdLogStrQueue.size(); +} + +bool ServerCmdLog::GetRunningStatus() +{ + return running_; +} + +void ServerCmdLog::SetRunningStatus(bool running) +{ + running_ = running; +} + +std::chrono::system_clock::time_point ServerCmdLog::GetLastFlushTime() +{ + return lastFlushTime; +} + +} // namespace Hdc \ No newline at end of file diff --git a/src/common/server_cmd_log.h b/src/common/server_cmd_log.h new file mode 100644 index 00000000..55913c91 --- /dev/null +++ b/src/common/server_cmd_log.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_CMD_LOG_H +#define HDC_CMD_LOG_H +#include +#include +#include + +namespace Hdc { +class ServerCmdLog { +public: + static ServerCmdLog& GetInstance(); + ServerCmdLog(); + ~ServerCmdLog(); + void PushCmdLogStr(const std::string& cmdLogStr); + std::string PopCmdLogStr(); + size_t CmdLogStrSize(); + bool GetRunningStatus(); + void SetRunningStatus(bool running); + std::chrono::system_clock::time_point GetLastFlushTime(); + +private: + bool running_ = false; + std::chrono::system_clock::time_point lastFlushTime = std::chrono::system_clock::now(); + std::mutex pushCmdLogStrRecordMutex; + std::queue pushCmdLogStrQueue; +}; +} // namespace Hdc +#endif // HDC_CMD_LOG_H \ No newline at end of file diff --git a/src/host/server.cpp b/src/host/server.cpp index f327e4c7..63255477 100644 --- a/src/host/server.cpp +++ b/src/host/server.cpp @@ -14,6 +14,7 @@ */ #include "server.h" #include "host_updater.h" +#include "server_cmd_log.h" namespace Hdc { @@ -119,6 +120,7 @@ bool HdcServer::Initial(const char *listenString) break; } #endif + Base::ProcessCmdLogs(); ret = true; } while (0); if (!ret) { @@ -1093,4 +1095,13 @@ void HdcServer::EchoToClientsForSession(uint32_t targetSessionId, const string & WRITE_LOG(LOG_INFO, "%s:%u %s", __FUNCTION__, targetSessionId, echo.c_str()); hSfc->EchoToAllChannelsViaSessionId(targetSessionId, echo); } + +void HdcServer::PrintCmdLogEx(const string& cmdStr) +{ + if (cmdStr.empty()) { + return; + } + Hdc::ServerCmdLog::GetInstance().PushCmdLogStr(cmdStr); +} + } // namespace Hdc diff --git a/src/host/server.h b/src/host/server.h old mode 100755 new mode 100644 index d36ec9e5..13d77e34 --- a/src/host/server.h +++ b/src/host/server.h @@ -45,7 +45,8 @@ public: #endif void *clsServerForClient; std::atomic lastErrorNum; - + void PrintCmdLogEx(const string &cmdStr); + private: void ClearInstanceResource() override; void BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out); diff --git a/src/host/server_for_client.cpp b/src/host/server_for_client.cpp old mode 100755 new mode 100644 index 99ade4fc..4c0b2909 --- a/src/host/server_for_client.cpp +++ b/src/host/server_for_client.cpp @@ -878,7 +878,7 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in if (!SendToDaemon(hChannel, command, bufPtr + sizeof(uint16_t), bytesIO - sizeof(uint16_t))) { WRITE_LOG(LOG_FATAL, "Client ReadChannel : direct send to daemon failed"); } - return ret; + return 0; } struct TranslateCommand::FormatCommand formatCommand = { 0 }; if (!hChannel->interactiveShellMode) { @@ -896,6 +896,10 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in WRITE_LOG(LOG_INFO, "ReadChannel cid:%u sid:%u key:%s command:%s", hChannel->channelId, hChannel->targetSessionId, Hdc::MaskString(hChannel->connectKey).c_str(), bufPtr); + if (Hdc::Base::GetCmdLogSwitch()) { + string logBuf = Base::CmdLogStringFormat(hChannel->targetSessionId, (reinterpret_cast(bufPtr))); + ptrServer->PrintCmdLogEx(logBuf); + } if (formatCommand.bJumpDo) { WRITE_LOG(LOG_FATAL, "ReadChannel bJumpDo true"); return -10; // -10 error formatCommand @@ -907,8 +911,7 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in if (!DoCommand(hChannel, &formatCommand, hdi)) { return -3; // -3: error or want close } - ret = bytesIO; - return ret; + return bytesIO; }; // avoid session dead diff --git a/src/host/translate.cpp b/src/host/translate.cpp old mode 100755 new mode 100644 index 1137c010..db2cd0d0 --- a/src/host/translate.cpp +++ b/src/host/translate.cpp @@ -205,6 +205,8 @@ namespace TranslateCommand { "OHOS_HDC_LOG_LEVEL - Set hdc server log level(range 0~5, default 5)\n" "OHOS_HDC_HEARTBEAT - Set whether the hdc heartbeat function is disabled\n" " (1: disabled, other: enabled, default: enabled)\n" + "OHOS_HDC_CMD_RECORD - Set whether the hdc command record function is enabled\n" + " (1: enabled, other: disabled, default: disabled)\n" #ifdef FEATURE_HOST_LOG_COMPRESS "OHOS_HDC_LOG_LIMIT - Set the number of logs that trigger the total" " log file size statistics (default 300 (files))\n" @@ -214,6 +216,8 @@ namespace TranslateCommand { "$OHOS_HDC_LOG_LEVEL - Set hdc server log level(range 0~5, default 5)\n" "$OHOS_HDC_HEARTBEAT - Set whether the hdc heartbeat function is disabled\n" " (1: disabled, other: enabled, default: enabled)\n" + "$OHOS_HDC_CMD_RECORD - Set whether the hdc command record function is enabled\n" + " (1: enabled, other: disabled, default: disabled)\n" #ifdef FEATURE_HOST_LOG_COMPRESS "$OHOS_HDC_LOG_LIMIT - Set the number of logs that trigger the total" " log file size statistics (default 300 (files))\n" -- Gitee From b56ef63a0861a0c93d33281ce7a214f3713fa9d3 Mon Sep 17 00:00:00 2001 From: luciferWei Date: Tue, 13 May 2025 09:10:27 +0800 Subject: [PATCH 2/2] =?UTF-8?q?Feat=EF=BC=9A=E5=A2=9E=E5=8A=A0=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E5=BD=95=E5=88=B6=E5=8A=9F=E8=83=BD=20=20\nSigned-off?= =?UTF-8?q?-by:=20LuciferWei=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/host/server_for_client.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/host/server_for_client.cpp b/src/host/server_for_client.cpp index 4c0b2909..f703de61 100644 --- a/src/host/server_for_client.cpp +++ b/src/host/server_for_client.cpp @@ -861,7 +861,6 @@ void HdcServerForClient::ReportServerVersion(HChannel hChannel) // Here is Server to get data, the source is the SERVER's ChildWork to send data int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) { - int ret = 0; if (!hChannel->handshakeOK) { return ChannelHandShake(hChannel, bufPtr, bytesIO); } -- Gitee