如何在Windows中使用R运行可执行文件并稍后终止或杀死同一进程

7
假设我有一个可执行文件存储在 c:\my directory\my file.exe,我想在我的 R 脚本开始时启动它,然后在 R 脚本结束时终止它。在 Windows 平台上,有哪些干净的方法可以实现这一点?
我知道 R 命令如 shellshell.exec,但我不确定这些命令是否允许干净地捕获进程 ID,然后使用类似于 pskill 函数。也不清楚通过某种类型的 管道连接 运行此可执行文件是否更合理 - 或者该管道如何工作。这个特定的可执行文件应该包含在我的 Windows PATH 中作为系统变量,因此 system 函数在这里也可能有价值。
额外的澄清:捕获进程 ID 可能很重要,因为(至少对我来说)这将用于数据库服务器的可执行文件 - 如果多个数据库服务器当前在同一台机器上运行,则进程不应该杀死所有这些进程 - 只需初始化 R 脚本开头的那个进程。
额外加分题:假设 c:\my directory\my file.exe 应该通过实际执行另一个文件 - c:\my directory\another file.bat - 调用,但需要在 R 脚本结束时杀死 my file.exe

首先感谢这个有趣的问题,我之前并不知道还有这种可能性,即 shell 和 pskill 函数。一个快速的想法是,你可以创建另一个名为 killfile.bat 的文件,使用通常的进程终止方式来终止进程(无论那是什么)。然后你可以在脚本的结尾以同样的方式运行该文件.bat。 - Jouni Helske
3个回答

5
从其他两个答案中得到的启发,这种技术似乎是实现所述目标的合理方法。
# specify executable file
exe.file <- "C:\\Users\\AnthonyD\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe"

# capture the result of a `tasklist` system call
before.win.tasklist <- system2( 'tasklist' , stdout = TRUE )

# store all pids before running the process
before.pids <- substr( before.win.tasklist[ -(1:3) ] , 27 , 35 )

# run the process
shell.exec( exe.file )

# capture the result of a `tasklist` system call
after.win.tasklist <- system2( 'tasklist' , stdout = TRUE )

# store all tasks after running the process
after.tasks <- substr( after.win.tasklist[ -(1:3) ] , 1 , 25 )

# store all pids after running the process
after.pids <- substr( after.win.tasklist[ -(1:3) ] , 27 , 35 )

# store the number in the task list containing the PIDs you've just initiated
initiated.pid.positions <- which( !( after.pids %in% before.pids ) )

# remove whitespace
after.tasks <- gsub( " " , "" , after.tasks )

# find the pid position that matches the executable file name
correct.pid.position <- 
    intersect(
        which( after.tasks %in% basename( exe.file ) ) ,
        initiated.pid.positions 
    )


# remove whitespace
correct.pid <- gsub( " " , "" , after.pids[ correct.pid.position ] )

# write the taskkill command line
taskkill.cmd <- paste( "taskkill" , "/PID" , correct.pid )

# wait thirty seconds (so the program fully loads)
Sys.sleep( 30 )

# kill the same process that was loaded
system( taskkill.cmd )

2
你可以使用 system 函数:
system("Taskkill /IM myfile.exe /F")

编辑:我在我的Windows 7电脑上测试过(通过结束 skype.exe 进程),这个方法有效。


2
这是一个很好的答案,但实际上可能会有多个具有相同名称的进程。我认为 OP 想要一种启动进程并获取其 ID 的方法,以便稍后可以使用 system("Taskkill /PID [pid]") 来终止它。 - Theodore Lytras
多进程的好处确实很不错,我之前没有想到过。 - Jouni Helske
@Hemmo 感谢您的留言和回答 :) Theodore 是正确的(我道歉),我已经对问题进行了澄清 - kill 命令需要区分在 R 脚本开始时运行的进程和其他具有相同可执行文件名称的进程。 - Anthony Damico

2

过去,我使用过PsKill。它非常强大,但也可能很危险。你可以在远程计算机上终止多个进程。我认为当我们想要粗暴地终止进程时,一定要非常小心。

  1. 下载该工具,解压并复制到已知路径。
  2. 第一次运行时会要求许可证。您可以通过 cmd 运行一次并同意许可证。

然后,您可以使用以下命令:

process_name <- 'your_process_name'
system(paste(path_to_pskil,'pskill ',process_name,sep=''),intern=T)

例如,要关闭所有 Chrome 实例,您可以执行以下操作:
system('c:/temp/pskill chrome',intern=T) !!

编辑

假设您有多个同名的进程。您可以使用pslist列出所有具有此名称的进程。根据其经过的时间找到要终止的进程的ID,然后按ID调用pskill

例如,在这里我想要终止最后启动的chrome进程。

my.process <- system('c:/temp/pslist chrome ',intern=T)[-c(1:8)]
my.process
[1] "chrome             3852   8  38 1052 141008     0:01:58.108     1:43:11.547"
[2] "chrome             5428   8  11  202 220392     0:02:08.092     1:43:11.359"
[3] "chrome             6228   8   9  146  73692     0:01:58.467     1:43:00.091"
[4] "chrome             6312   6   9  130  45420     0:00:08.704     1:17:30.153"
[5] "chrome              360   6   9  127  29252     0:00:01.263     0:57:01.084"
[6] "chrome             5032   6   9  126  29596     0:00:00.717     0:31:39.875"
[7] "chrome             2572   8   9  120  23816     0:00:00.452     0:19:10.307"
## ids are orderd according to the elpased time
## I use tail to get the last one
## some regular expression to get the id from the string 
## mine is  ugly but I am sure you can do better.
id <- substr(gsub("([^[:digit:]]*)", "",  tail(my.process,1)),1,4)
system(paste('c:/temp/pskill ', id) ,intern=T)

感谢 @agstudy..当进程在一开始初始化时,你如何确定进程名称? - Anthony Damico
@AnthonyDamico,你有关于这个进程的什么信息?例如启动时间?我需要更多的信息。 - agstudy
开始任何你想要的进程,都没有问题。比如C:\Users\AnthonyD\AppData\Local\Google\Chrome\Application\chrome.exe,你可以以任何方式运行该可执行文件来捕获信息,但当 R 脚本终止时,需要终止适当的 chrome.exe(假设有多个正在运行)。 - Anthony Damico
@AnthonyDamico 你可以看到我的更新。 - agstudy
不错。显然,tasklist可以获取进程而不需要外部软件的支持。 - Anthony Damico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接