From 094d8dc6c47652074b249b5e28f6589ed7cb9f5f Mon Sep 17 00:00:00 2001 From: queyanwen Date: Sun, 28 Apr 2024 12:08:43 +0800 Subject: [PATCH] =?UTF-8?q?powerapi:=E4=BA=8B=E4=BB=B6=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E6=9C=BA=E5=88=B6=E4=BC=98=E5=8C=96=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=8A=A2=E5=8D=A0=E9=85=8D=E7=BD=AE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/inc/pwrdata.h | 1 - pwrapic/gtest/Common.cpp | 12 ++++++-- pwrapic/inc/sockclient.h | 10 +++++++ pwrapic/src/CMakeLists.txt | 4 +-- pwrapic/src/powerapi.c | 22 +++++--------- pwrapic/src/sockclient.c | 35 +++++++++++++++++----- pwrapic/test/demo_main.c | 16 ++++++++-- pwrapis/inc/common.h | 1 + pwrapis/inc/pwrclient.h | 4 +++ pwrapis/inc/server.h | 2 ++ pwrapis/src/comservice.c | 18 ++++++++---- pwrapis/src/log.c | 2 +- pwrapis/src/main_frame.c | 2 -- pwrapis/src/pwrclient.c | 10 +++++++ pwrapis/src/server.c | 60 +++++++++++++++++++++++++------------- pwrapis/src/taskservice.c | 1 - uninstall.sh | 4 ++- 17 files changed, 145 insertions(+), 59 deletions(-) diff --git a/common/inc/pwrdata.h b/common/inc/pwrdata.h index e3c396b..e8bcb6e 100644 --- a/common/inc/pwrdata.h +++ b/common/inc/pwrdata.h @@ -37,7 +37,6 @@ #define PWR_DECIMAL 10 #define PWR_CONVERSION 1000 #define PWR_MAX_CPU_ID_WIDTH 5 -#define PWR_MAX_INPUT_NUM 512 #define PWR_MAX_GOV_ATTR_NUM 20 #define PWR_MAX_IDLE_GOV_NUM 8 #define PWR_MAX_CPU_CSTATE_NUM 10 diff --git a/pwrapic/gtest/Common.cpp b/pwrapic/gtest/Common.cpp index 9bc9a55..6fc0c24 100644 --- a/pwrapic/gtest/Common.cpp +++ b/pwrapic/gtest/Common.cpp @@ -83,13 +83,21 @@ void MetaDataCallback(const PWR_COM_CallbackData *callbackData) } } +static void PrintEventInfo(const PWR_COM_EventInfo *eventInfo) +{ + printf("[Event] ctime:%s, type:%d\n", eventInfo->ctime, eventInfo->eventType); + if (eventInfo->infoLen > 0 && eventInfo->info) { + printf("[Event] info:%s\n", eventInfo->info); + } +} + void EventCallback(const PWR_COM_EventInfo *eventInfo) { printf("[Event] Get event notification\n"); switch (eventInfo->eventType) { case PWR_COM_EVTTYPE_CRED_FAILED: - printf("[Event] ctime:%s, type:%d\n", eventInfo->ctime, eventInfo->eventType); - printf("[Event] info:%s\n", eventInfo->info); + case PWR_COM_EVTTYPE_AUTH_RELEASED: + PrintEventInfo(eventInfo); break; default: printf("[Event] Get invalid event.\n"); diff --git a/pwrapic/inc/sockclient.h b/pwrapic/inc/sockclient.h index b1be3d8..dde3f82 100644 --- a/pwrapic/inc/sockclient.h +++ b/pwrapic/inc/sockclient.h @@ -29,6 +29,12 @@ typedef struct RspOutputParam { char *rspData; } RspOutputParam; +typedef enum PwrApiStatus { + STATUS_UNREGISTERED = 0, + STATUS_REGISTERTED = 1, + STATUS_AUTHED = 2, +} PwrApiStatus; + int SetServerInfo(const char* socketPath); int InitSockClient(void); int FiniSockClient(void); @@ -36,4 +42,8 @@ int SetMetaDataCallback(void(MetaDataCallback)(const PWR_COM_CallbackData *)); int SetEventCallback(void(EventCallback)(const PWR_COM_EventInfo *)); int HasSetDataCallback(void); int SendReqAndWaitForRsp(const ReqInputParam input, RspOutputParam output); + +PwrApiStatus GetPwrApiStatus(); +int SetPwrApiStatus(PwrApiStatus status); + #endif diff --git a/pwrapic/src/CMakeLists.txt b/pwrapic/src/CMakeLists.txt index eacb20f..4fee95d 100644 --- a/pwrapic/src/CMakeLists.txt +++ b/pwrapic/src/CMakeLists.txt @@ -22,9 +22,9 @@ if(BUILD_LLT) endif(BUILD_LLT) # set installation path -set ( CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Install path prefix" FORCE) +set ( CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install path prefix" FORCE) #install (TARGETS ${PG_NAME} DESTINATION sbin) -install (TARGETS ${PG_NAME} DESTINATION lib) +install (TARGETS ${PG_NAME} DESTINATION lib64) # Release compile mode # set(CMAKE_BUILD_TYPE "Release") diff --git a/pwrapic/src/powerapi.c b/pwrapic/src/powerapi.c index 3d903e9..3724178 100644 --- a/pwrapic/src/powerapi.c +++ b/pwrapic/src/powerapi.c @@ -28,17 +28,9 @@ #include "pwrusb.h" #include "pwrproc.h" -typedef enum PwrApiStatus { - STATUS_UNREGISTERED = 0, - STATUS_REGISTERTED = 1, - STATUS_AUTHED = 2, -} PwrApiStatus; - -static PwrApiStatus g_status = STATUS_UNREGISTERED; - #define CHECK_STATUS(s) \ { \ - if ((s) > g_status) { \ + if ((s) > GetPwrApiStatus()) { \ if ((s) == STATUS_REGISTERTED) { \ PwrLog(ERROR, "Not registed."); \ return PWR_ERR_NOT_REGISTED; \ @@ -107,14 +99,14 @@ int PWR_SetServerInfo(const char* socketPath) int PWR_Register(void) { - if (g_status != STATUS_UNREGISTERED) { + if (GetPwrApiStatus() != STATUS_UNREGISTERED) { return PWR_SUCCESS; } if (InitSockClient() != PWR_SUCCESS) { return PWR_ERR_COMMON; } - if (g_status == STATUS_UNREGISTERED) { - g_status = STATUS_REGISTERTED; + if (GetPwrApiStatus() == STATUS_UNREGISTERED) { + (void)SetPwrApiStatus(STATUS_REGISTERTED); } return PWR_SUCCESS; } @@ -122,7 +114,7 @@ int PWR_Register(void) int PWR_UnRegister(void) { int ret = FiniSockClient(); - g_status = STATUS_UNREGISTERED; + (void)SetPwrApiStatus(STATUS_UNREGISTERED); return ret; } @@ -132,7 +124,7 @@ int PWR_RequestControlAuth(void) CHECK_STATUS(STATUS_REGISTERTED); int ret = RequestControlAuth(); if (ret == PWR_SUCCESS) { - g_status = STATUS_AUTHED; + (void)SetPwrApiStatus(STATUS_AUTHED); } return ret; } @@ -142,7 +134,7 @@ int PWR_ReleaseControlAuth(void) CHECK_STATUS(STATUS_AUTHED); int ret = ReleaseControlAuth(); if (ret == PWR_SUCCESS) { - g_status = STATUS_REGISTERTED; + (void)SetPwrApiStatus(STATUS_REGISTERTED); } return ret; } diff --git a/pwrapic/src/sockclient.c b/pwrapic/src/sockclient.c index fdc3add..45a62df 100644 --- a/pwrapic/src/sockclient.c +++ b/pwrapic/src/sockclient.c @@ -45,6 +45,7 @@ static PwrMsgBuffer g_sendBuff; // Send queue static PwrMsgBuffer g_recvBuff; // Receive queue static ResultWaitingMsgList g_waitList; // Waiting for results list static char SERVER_ADDR[MAX_PATH_LEN] = "/etc/sysconfig/pwrapis/pwrserver.sock"; // Default server path +static PwrApiStatus g_status = STATUS_UNREGISTERED; #define CHECK_SOCKET_STATUS() \ if (g_sockFd == INVALID_FD) { \ @@ -121,6 +122,18 @@ static void DoDataCallback(PwrMsg *msg) ReleasePwrMsg(&msg); } +static int EventPreProcessing(const PWR_COM_EventInfo *event) +{ + switch (event->eventType) { + case PWR_COM_EVTTYPE_AUTH_RELEASED: + SetPwrApiStatus(STATUS_REGISTERTED); + break; + default: + break; + } + return PWR_SUCCESS; +} + static void DefaultEventCallback(const PWR_COM_EventInfo *eventInfo) { printf("[Event] ctime:%s, type:%d, info:%s\n", eventInfo->ctime, @@ -136,13 +149,10 @@ static void DoEventCallback(PwrMsg *msg) return; } PWR_COM_EventInfo *callbackEvent = (PWR_COM_EventInfo *)msg->data; - if (callbackEvent->infoLen <= 0) { - PwrLog(DEBUG, "DoEventCallback. data empty. len: %d", callbackEvent->infoLen); - ReleasePwrMsg(&msg); - return; - } + (void)EventPreProcessing(callbackEvent); + if (g_event_callback == NULL) { - PwrLog(ERROR, "No event callback."); + PwrLog(ERROR, "No event callback function."); ReleasePwrMsg(&msg); return; } @@ -501,4 +511,15 @@ int SendReqAndWaitForRsp(const ReqInputParam input, RspOutputParam output) ReleasePwrMsg(&req); ReleasePwrMsg(&rsp); return PWR_SUCCESS; -} \ No newline at end of file +} + +PwrApiStatus GetPwrApiStatus() +{ + return g_status; +} + +int SetPwrApiStatus(PwrApiStatus status) +{ + g_status = status; + return PWR_SUCCESS; +} diff --git a/pwrapic/test/demo_main.c b/pwrapic/test/demo_main.c index dd571af..663e230 100644 --- a/pwrapic/test/demo_main.c +++ b/pwrapic/test/demo_main.c @@ -45,6 +45,14 @@ static void PrintResult(char *function, int ret) } } +static void PrintEventInfo(const PWR_COM_EventInfo *eventInfo) +{ + printf("[Event] ctime:%s, type: %d\n", eventInfo->ctime, eventInfo->eventType); + if (eventInfo->infoLen > 0 && eventInfo->info) { + printf("[Event] info:%s\n", eventInfo->info); + } +} + enum { DEBUG = 0, INFO, @@ -116,8 +124,12 @@ void EventCallback(const PWR_COM_EventInfo *eventInfo) printf("[Event] Get event notification\n"); switch (eventInfo->eventType) { case PWR_COM_EVTTYPE_CRED_FAILED: - printf("[Event] ctime: %s, type: %d, info: %s\n", eventInfo->ctime, - eventInfo->eventType, eventInfo->info); + PrintEventInfo(eventInfo); + break; + case PWR_COM_EVTTYPE_AUTH_RELEASED: + PrintEventInfo(eventInfo); + printf("Control auth was released. app exit.\n"); + g_run = 0; break; default: printf("[Event] Get invalid event.\n"); diff --git a/pwrapis/inc/common.h b/pwrapis/inc/common.h index 73d2390..8530d7e 100644 --- a/pwrapis/inc/common.h +++ b/pwrapis/inc/common.h @@ -57,6 +57,7 @@ #define MD_NM_SVR_DISK "DISK_SERVICE" #define MD_NM_SVR_TASK "TASK_SERVICE" #define MD_NM_SVR_PROC "PROC_SERVICE" +#define MD_NM_SVR_COM "COM_SERVICE" #define MD_NM_CRED "CREDENTIALS" #define MD_NM_OTHS "OTHERS" diff --git a/pwrapis/inc/pwrclient.h b/pwrapis/inc/pwrclient.h index a1f9320..733dd4c 100644 --- a/pwrapis/inc/pwrclient.h +++ b/pwrapis/inc/pwrclient.h @@ -16,9 +16,11 @@ #define PAPIS_CLIENT_H__ #include +#include "pwrdata.h" typedef struct PwrClient { int fd; int sysId; + char userName[PWR_MAX_ELEMENT_NAME_LEN]; } PwrClient; void InitPwrClient(PwrClient clients[]); @@ -27,4 +29,6 @@ int DeleteFromClientList(PwrClient clients[], int idx); void CloseAllConnections(PwrClient clients[]); int GetFdBySysId(const PwrClient clients[], uint32_t sysId); int GetIdxByFd(const PwrClient clients[], int fd); +const char *GetUserNameBySysId(const PwrClient clients[], uint32_t sysId); + #endif diff --git a/pwrapis/inc/server.h b/pwrapis/inc/server.h index c2178dc..052d549 100644 --- a/pwrapis/inc/server.h +++ b/pwrapis/inc/server.h @@ -39,5 +39,7 @@ void StopServer(void); void SendRspToClient(const PwrMsg *req, int rspCode, char *data, uint32_t len); int SendMetadataToClient(uint32_t sysId, char *data, uint32_t len); int SendRspMsg(PwrMsg *rsp); +int SendEventToClient(uint32_t sysId, PWR_COM_EVT_TYPE type, void *info, uint32_t infoLen); +int IsInternalUser(uint32_t sysId); #endif \ No newline at end of file diff --git a/pwrapis/src/comservice.c b/pwrapis/src/comservice.c index 7a95825..b8ef80e 100644 --- a/pwrapis/src/comservice.c +++ b/pwrapis/src/comservice.c @@ -32,19 +32,27 @@ static int DoAuthRequest(uint32_t client) UnixCredOS credOS; int ret = GetSockoptFromOS(client, &credOS); if (ret != PWR_SUCCESS) { - Logger(ERROR, MD_NM_SVR_TASK, "get sockopt from OS failed, ret : %d", ret); + Logger(ERROR, MD_NM_SVR_COM, "get sockopt from OS failed, ret : %d", ret); return PWR_ERR_COMMON; } if (!IsAdmin(credOS.user)) { - Logger(ERROR, MD_NM_SVR_TASK, "the client <%s> is not an admin", credOS.user); + Logger(ERROR, MD_NM_SVR_COM, "the client <%s> is not an admin", credOS.user); return PWR_ERR_CONTROL_AUTH_NO_PERMISSION; } if (g_authed) { - if (g_authOwner != client) { // Control has been granted to other app - return PWR_ERR_CONTROL_AUTH_REQUESTED; + if (g_authOwner == client) { + return PWR_SUCCESS; } - return PWR_SUCCESS; + // Control auth has been granted to other client + if (IsInternalUser(g_authOwner)) { + (void)SendEventToClient(g_authOwner, PWR_COM_EVTTYPE_AUTH_RELEASED, NULL, 0); + Logger(INFO, MD_NM_SVR_COM, "Auth owned by force released by %s", + g_authOwner, credOS.user, client); + g_authOwner = client; + return PWR_SUCCESS; + } + return PWR_ERR_CONTROL_AUTH_REQUESTED; } g_authOwner = client; g_authed = PWR_TRUE; diff --git a/pwrapis/src/log.c b/pwrapis/src/log.c index ae619c2..488ef87 100644 --- a/pwrapis/src/log.c +++ b/pwrapis/src/log.c @@ -33,7 +33,7 @@ #define CRT_DIR_MODE 0700 -static FILE *g_pFile = NULL; // todo 需要mutex保护 +static FILE *g_pFile = NULL; // 需要mutex保护? static uint32_t g_curSize = 0; static regex_t g_logCmpFlRgx; diff --git a/pwrapis/src/main_frame.c b/pwrapis/src/main_frame.c index 92882e0..03b6309 100644 --- a/pwrapis/src/main_frame.c +++ b/pwrapis/src/main_frame.c @@ -42,7 +42,6 @@ static int BaseInit(void) return ret; } - // todo 其他必要的初始化 return PWR_SUCCESS; } @@ -98,7 +97,6 @@ int main(int argc, const char *args[]) while (g_keepMainRunning) { sleep(MAIN_LOOP_INTERVAL); CheckAndUpdateConfig(); - // todo 系统定时任务(比如配置文件更新)触发 } StopServer(); ClearEnv(); diff --git a/pwrapis/src/pwrclient.c b/pwrapis/src/pwrclient.c index 8892d3e..fc7c27d 100644 --- a/pwrapis/src/pwrclient.c +++ b/pwrapis/src/pwrclient.c @@ -111,4 +111,14 @@ int GetIdxByFd(const PwrClient clients[], int fd) } } return INVALID_INDEX; +} + +const char *GetUserNameBySysId(const PwrClient clients[], uint32_t sysId) +{ + for (int i = 0; i < MAX_CLIENT_NUM; i++) { + if (clients[i].sysId == sysId) { + return clients[i].userName; + } + } + return NULL; } \ No newline at end of file diff --git a/pwrapis/src/server.c b/pwrapis/src/server.c index 32e6972..1e1ce0b 100644 --- a/pwrapis/src/server.c +++ b/pwrapis/src/server.c @@ -139,7 +139,7 @@ static void StopListen(void) pthread_mutex_unlock(&g_listenFdLock); } -static int PassCredVerification(const struct ucred *credSocket) +static int PassCredVerification(const struct ucred *credSocket, char *userName) { int ret; UnixCredOS credOS = {0}; @@ -156,16 +156,16 @@ static int PassCredVerification(const struct ucred *credSocket) } if (!IsAdmin(credOS.user) && !IsObserver(credOS.user)) { - Logger(ERROR, MD_NM_SVR, "the client <%s> is not in white list", credOS.user); + Logger(ERROR, MD_NM_SVR, "the client <%s> has no admin permission!", credOS.user); return PWR_ERR_COMMON; } - + strncpy(userName, credOS.user, PWR_MAX_ELEMENT_NAME_LEN); return PWR_SUCCESS; } -static PWR_COM_EventInfo* CreateEventInfo(const char *info, PWR_COM_EVT_TYPE eventType) +static PWR_COM_EventInfo* CreateEventInfo(PWR_COM_EVT_TYPE eventType, const void *info, uint32_t len) { - size_t eventInfoLen = sizeof(PWR_COM_EventInfo) + strlen(info) + 1; + size_t eventInfoLen = sizeof(PWR_COM_EventInfo) + len; PWR_COM_EventInfo *eventInfo = (PWR_COM_EventInfo *)malloc(eventInfoLen); if (!eventInfo) { return NULL; @@ -174,12 +174,12 @@ static PWR_COM_EventInfo* CreateEventInfo(const char *info, PWR_COM_EVT_TYPE eve bzero(eventInfo, sizeof(eventInfoLen)); GetCurFullTime(eventInfo->ctime, PWR_MAX_TIME_LEN); eventInfo->eventType = eventType; - eventInfo->infoLen = strlen(info) + 1; - strcpy(eventInfo->info, info); + eventInfo->infoLen = len; + memcpy(eventInfo->info, info, len); return eventInfo; } -static int SendEventToClient(const int dstFd, const uint32_t sysId, char *data, uint32_t len); +static int DoSendEventToClient(const int dstFd, const uint32_t sysId, char *data, uint32_t len); static void AcceptConnection(void) { Logger(INFO, MD_NM_SVR, "Received connection request."); @@ -195,33 +195,32 @@ static void AcceptConnection(void) return; } - /*todo 链路保活,IPC场景下优先级放低,后续完善 */ struct ucred credSocket; if (getsockopt(newClientFd, SOL_SOCKET, SO_PEERCRED, &credSocket, &socklen) < 0) { Logger(ERROR, MD_NM_SVR, "get sock options failed"); return; } - if (PassCredVerification(&credSocket) != PWR_SUCCESS) { + PwrClient client = {0}; + client.fd = newClientFd; + client.sysId = credSocket.pid; + if (PassCredVerification(&credSocket, client.userName) != PWR_SUCCESS) { Logger(ERROR, MD_NM_CRED, "credentials verification failed"); - const char *info = "Server has closed connection. This client is not in white list"; + const char *info = "Server has closed connection. This client has no admin permission."; /* eventData should be release in the function that uses it */ - PWR_COM_EventInfo *eventInfo = CreateEventInfo(info, PWR_COM_EVTTYPE_CRED_FAILED); + PWR_COM_EventInfo *eventInfo = CreateEventInfo(PWR_COM_EVTTYPE_CRED_FAILED, info, strlen(info) + 1); if (!eventInfo) { Logger(ERROR, MD_NM_SVR, "Create event failed."); close(newClientFd); return; } - SendEventToClient(newClientFd, credSocket.pid, (char *)eventInfo, + DoSendEventToClient(newClientFd, credSocket.pid, (char *)eventInfo, sizeof(PWR_COM_EventInfo) + strlen(info) + 1); close(newClientFd); return; } - PwrClient client; - client.fd = newClientFd; - client.sysId = credSocket.pid; if (AddToClientList(g_pwrClients, client) != PWR_SUCCESS) { Logger(ERROR, MD_NM_SVR, "Reach maximum connections or client existed : %d ", MAX_CLIENT_NUM); close(newClientFd); @@ -343,7 +342,7 @@ static int WriteMsg(const void *pData, size_t len, int dstFd) return PWR_SUCCESS; } -static void SendMsgToClientAction(int dstFd, PwrMsg *msg) +static void DoSendMsgToClient(int dstFd, PwrMsg *msg) { static char data[MAX_DATA_SIZE]; size_t len = sizeof(PwrMsg) + msg->head.dataLen; @@ -370,7 +369,7 @@ static void SendMsgToClientAction(int dstFd, PwrMsg *msg) } } -static int SendEventToClient(const int dstFd, const uint32_t sysId, char *data, uint32_t len) +static int DoSendEventToClient(const int dstFd, const uint32_t sysId, char *data, uint32_t len) { if (!data && len != 0) { return PWR_ERR_INVALIDE_PARAM; @@ -393,7 +392,7 @@ static int SendEventToClient(const int dstFd, const uint32_t sysId, char *data, return res; } - SendMsgToClientAction(dstFd, event); + DoSendMsgToClient(dstFd, event); Logger(INFO, MD_NM_SVR, "Send event notifcation success."); ReleasePwrMsg(&event); // This will free(data) return PWR_SUCCESS; @@ -415,7 +414,7 @@ static void ProcessSendMsgToClient(void) ReleasePwrMsg(&msg); continue; } - SendMsgToClientAction(dstFd, msg); + DoSendMsgToClient(dstFd, msg); Logger(DEBUG, MD_NM_SVR, "send msg. opt:%d, sysId:%d, rspCode:%d", msg->head.optType, msg->head.sysId, msg->head.rspCode); ReleasePwrMsg(&msg); @@ -652,3 +651,24 @@ int SendRspMsg(PwrMsg *rsp) { return AddToBufferTail(&g_sendBuff, rsp); } + +int SendEventToClient(uint32_t sysId, PWR_COM_EVT_TYPE type, void *info, uint32_t infoLen) +{ + PWR_COM_EventInfo *eventInfo = CreateEventInfo(type, info, infoLen); + if (!eventInfo) { + Logger(ERROR, MD_NM_SVR, "Create event failed."); + return PWR_ERR_SYS_EXCEPTION; + } + int fd = GetFdBySysId(g_pwrClients, sysId); + return DoSendEventToClient(fd, sysId, (char *)eventInfo, sizeof(PWR_COM_EventInfo) + infoLen); +} + +static const char INTERNAL_USER[] = "eagle"; +int IsInternalUser(uint32_t sysId) +{ + const char *name = GetUserNameBySysId(g_pwrClients, sysId); + if (name && strcmp(INTERNAL_USER, name) == 0) { + return PWR_TRUE; + } + return PWR_FALSE; +} diff --git a/pwrapis/src/taskservice.c b/pwrapis/src/taskservice.c index 0a83461..577095f 100644 --- a/pwrapis/src/taskservice.c +++ b/pwrapis/src/taskservice.c @@ -12,7 +12,6 @@ * Create: 2022-11-05 * Description: provide task service * **************************************************************************** */ -// todo: socket断链时,需要考虑task的释放 #include "taskservice.h" #include diff --git a/uninstall.sh b/uninstall.sh index 29ab1d3..1a69a3f 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -7,7 +7,9 @@ if [ -f "./build/install_manifest.txt" ];then cd build xargs rm < install_manifest.txt else - rm /usr/lib/libpwrapi.so + rm /usr/include/pwrapic/* + rm /usr/lib64/libpwrapi.so + rm /usr/sbin/pwrapis rm /etc/sysconfig/pwrapis/pwrapis_config.ini rm /usr/lib/systemd/system/pwrapis.service -- Gitee