int CEclAgentExecutionServer::executeWorkunit(const char * wuid) { //build eclagent command line StringBuffer command; #ifdef _WIN32 command.append(".\\eclagent.exe"); #else command.append("start_eclagent"); #endif StringBuffer cmdLine = command; cmdLine.append(" WUID=").append(wuid).append(" DALISERVERS=").append(daliServers); DWORD runcode; PROGLOG("AgentExec: Executing '%s'", cmdLine.str()); #ifdef _WIN32 bool success = invoke_program(cmdLine.str(), runcode, false, NULL, NULL); #else //specify "wait" to eliminate linux zombies. Waits for the startup script to //complete (not eclagent), because script starts eclagent in the background bool success = invoke_program(cmdLine.str(), runcode, true, NULL, NULL); #endif if (success) { if (runcode != 0) PROGLOG("Process failed during execution: %s error(%"I64F"i)", cmdLine.str(), (unsigned __int64) runcode); else PROGLOG("Execution started"); } else { Owned<IWorkUnitFactory> factory = getWorkUnitFactory(); Owned<IWorkUnit> workunit = factory->updateWorkUnit(wuid); if (workunit) { workunit->setState(WUStateFailed); workunit->commit(); } PROGLOG("Process failed to start: %s", cmdLine.str()); } return success && runcode == 0; }
int newagent::start_process(const char *command,int & error_code,const char * local_dir,const char * user,const char * password) { error_code=0; #ifdef _WIN32 PROCESS_INFORMATION process; STARTUPINFO si; HANDLE res=0; bool ok=false; HANDLE other_user=0; #ifdef _DEBUG if (!strcmp(command,"forceerror")) *((int *)0)=5; #endif memset(&si,0,sizeof(si)); si.cb = sizeof(si); si.lpTitle = (char*)command; si.wShowWindow = SW_SHOWDEFAULT; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; char current_dir[256]=" ;103<;01",c_dir[256]; if (local_dir&&*local_dir) { strcpy(c_dir,local_dir); } else { if (!is_debug_session&&read_key("03",(unsigned char *)current_dir,sizeof(current_dir))) { char * finger=current_dir; int bs=4; while (*finger&&bs) { if (*finger=='\\') bs--; finger++; } if (*finger) sprintf(c_dir,maped_drive"\\%s",finger); else sprintf(c_dir,maped_drive"\\"); } else strcpy(c_dir,"."); } if (is_debug_session) { ok=(bool)CreateProcess(NULL,(char*)command,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,c_dir,&si,&process); if (!ok) error_code=GetLastError(); } else { if (!local_dir&&!drive_maped) do_map_drive(error_code); if(!error_code) { HANDLE uh=server_user; if (user&&*user) { logonu(other_user,unscr((char*)user),unscr((char*)password),error_code); uh=other_user; } if (!error_code) { if (!ImpersonateLoggedOnUser(uh)) error_code=GetLastError(); if (!error_code) { char saved_dir[256]; if (!GetCurrentDirectory(sizeof(saved_dir),saved_dir)) { logfile("GetCurrentDirectory failed\r\n"); error_code=GetLastError(); } else { if (!SetCurrentDirectory(c_dir)) { error_code=GetLastError(); if (error_code==2) error_code=267; logfile ("SetCurrentDirectory failed %s %i\r\n",c_dir,error_code); } else { ok=(bool)CreateProcessAsUser( uh,NULL,(char*)command,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,c_dir,&si,&process); if (!ok) error_code=GetLastError(); if (ok&&!SetCurrentDirectory(saved_dir)) { logfile("restore current dirctory failed %s\r\n",saved_dir); error_code=GetLastError(); } } } RevertToSelf(); } } } } if (ok) { res=process.hProcess; CloseHandle(process.hThread); logfile("Process started: %s\r\n",command); } else { logfile("Process failed: %s error(%i) %s\r\n",command,error_code,c_dir); } if (other_user) CloseHandle(other_user); if (ok) return (int)res; else return 0; #else // if (is_debug_session) { long res; _chdir(cur_dir); pid_t pid; if (invoke_program(command, res, false, NULL, NULL, &pid)) return pid; printf("invoke_program error %d\n", res); error_code=res; logfile("Process failed: %s error(%i) %s\r\n",command,error_code,cur_dir); /* not sure these should be freed here free(user); free(password); */ return 0; } #endif }
virtual void doWork() { try { StringBuffer cmdLine; StringBuffer userId; StringBuffer password; bool bLinux; int exitCode = -1; if (m_sConfigAddress.length() < 1) { m_pService->getAccountAndPlatformInfo(m_sAddress.str(), userId, password, bLinux); } else { m_pService->getAccountAndPlatformInfo(m_sConfigAddress.str(), userId, password, bLinux); } if (m_userId.length() < 1 || m_userId.length() < 1) { //BUG: 9825 - remote execution on linux needs to use individual accounts //use userid/password in ESP context for remote execution... if (bLinux) { userId.clear(); password.clear(); m_context.getUserID(userId); m_context.getPassword(password); } } else { userId.clear().append(m_userId); password.clear().append(m_password); } #ifdef _WIN32 ///#define CHECK_LINUX_COMMAND #ifndef CHECK_LINUX_COMMAND #define popen _popen #define pclose _pclose // Use psexec as default remote control program if (bLinux) { if (!checkFileExists(".\\plink.exe")) throw MakeStringException(ECLWATCH_PLINK_NOT_INSTALLED, "Invalid ESP installation: missing plink.exe to execute the remote program!"); m_sCommand.replace('\\', '/');//replace all '\\' by '/' /* note that if we use plink (cmd line ssh client) for the first time with a computer, it generates the following message: The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is. The server's key fingerprint is: 1024 aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp If you trust this host, enter "y" to add the key to PuTTY's cache and carry on connecting. If you want to carry on connecting just once, without adding the key to the cache, enter "n".If you do not trust this host, press Return to abandon the connection. To get around this, we pipe "n" to plink without using its -batch parameter. We need help from cmd.exe to do this though... */ if (!m_useDefaultSSHUserID) { cmdLine.appendf("cmd /c \"echo y | .\\plink.exe -ssh -l espuser -i id_rsa.ppk %s bash -c '%s' 2>&1\"", m_sAddress.str(), m_sCommand.str()); } else { cmdLine.appendf("cmd /c \"echo y | .\\plink.exe -ssh -l %s -pw %s %s sudo bash -c '%s' 2>&1\"", userId.str(), password.str(), m_sAddress.str(), m_sCommand.str()); } } else { if (!checkFileExists(".\\psexec.exe")) throw MakeStringException(ECLWATCH_PSEXEC_NOT_INSTALLED, "Invalid ESP installation: missing psexec.exe to execute the remote program!"); cmdLine.appendf(".\\psexec \\\\%s -u %s -p %s %s cmd /c %s 2>&1", m_sAddress.str(), userId.str(), password.str(), m_bWait ? "" : "-d", m_sCommand.str()); } #else if (bLinux) { if (!m_useDefaultSSHUserID) { m_sCommand.replace('\\', '/');//replace all '\\' by '/' cmdLine.appendf("ssh -o StrictHostKeyChecking=no -i /home/espuser/.ssh/id_rsa espuser@%s '%s'", m_sAddress.str(), m_sCommand.str()); } else { m_sCommand.replace('\\', '/');//replace all '\\' by '/' cmdLine.appendf("ssh -o StrictHostKeyChecking=no %s '%s'", m_sAddress.str(), m_sCommand.str()); } } else { setResponse("Remote execution from Linux to Windows is not supported!"); exitCode = 1; } #endif #else if (bLinux) { if (!m_useDefaultSSHUserID) { m_sCommand.replace('\\', '/');//replace all '\\' by '/' cmdLine.appendf("ssh -o StrictHostKeyChecking=no -i /home/espuser/.ssh/id_rsa espuser@%s '%s'", m_sAddress.str(), m_sCommand.str()); } else { m_sCommand.replace('\\', '/');//replace all '\\' by '/' cmdLine.appendf("ssh -o StrictHostKeyChecking=no %s '%s'", m_sAddress.str(), m_sCommand.str()); } } else { setResponse("Remote execution from Linux to Windows is not supported!"); exitCode = 1; } #endif if (*cmdLine.str()) { if (m_bWait) { StringBuffer response, response1; exitCode = invoke_program(cmdLine, response); if (exitCode < 0) response1.append("Failed in executing a system command.\n"); else response1.append("System command(s) has been executed.\n"); //remove \n at the end int len = response.length(); if (len > 0 && response.charAt(--len) == '\n') response.setLength(len); setResponse(response1.str()); } else { DWORD runCode; ::invoke_program(cmdLine, runCode, false); exitCode = (int) runCode; } } setResultCode(exitCode); } catch(IException* e) { StringBuffer buf; e->errorMessage(buf); setResponse(buf.str()); setResultCode(e->errorCode()); } #ifndef NO_CATCHALL catch(...) { setResponse("An unknown exception occurred!"); setResultCode(-1); } #endif }//doWork()