You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

webshot::webshot()遗留未关闭文件连接的原因及自动关闭方法

问题:webshot::webshot()遗留FIFO连接导致R CMD check报错

在R包函数中使用webshot::webshot(),且在roxygen2头文件中提供可运行示例时,执行R CMD check会触发如下错误:

Error: connections left open:
/tmp/... (fifo)
/tmp/... (fifo)
Execution halted

该问题可在包环境外复现,步骤如下:

# 查看初始连接
showConnections(all = TRUE)

输出:

description class      mode text   isopen   can read can write
0 "stdin"     "terminal" "r"  "text" "opened" "yes"    "no"     
1 "stdout"    "terminal" "w"  "text" "opened" "no"     "yes"    
2 "stderr"    "terminal" "w"  "text" "opened" "no"     "yes"    
# 执行webshot(部分OS需设置OPENSSL_CONF)
Sys.setenv(OPENSSL_CONF = "/dev/null") # 依OS决定是否需要
webshot::webshot("https://github.com/rstudio/shiny") # 使用webshot 0.5.5版本
Sys.unsetenv(OPENSSL_CONF) # 依OS决定是否需要

# 再次查看连接
showConnections(all = TRUE)

输出:

description                      class      mode text   isopen   can read can write
0 "stdin"                          "terminal" "r"  "text" "opened" "yes"    "no"     
1 "stdout"                         "terminal" "w"  "text" "opened" "no"     "yes"    
2 "stderr"                         "terminal" "w"  "text" "opened" "no"     "yes"    
3 "/tmp/..."                       "fifo"     "w+" "text" "opened" "yes"    "yes"    
4 "/tmp/..."                       "fifo"     "w+" "text" "opened" "yes"    "yes"    

原因分析

webshot 0.5.5依赖PhantomJS作为截图引擎,PhantomJS启动时会创建FIFO管道(命名管道),用于和R进程双向通信,传递截图指令与结果。在交互式环境中,这些连接可能会被自动回收,但在非交互式环境(如R CMD check运行示例)中,PhantomJS进程退出后,R端未自动触发FIFO连接的关闭逻辑,导致连接残留。


解决方法

1. 手动关闭遗留FIFO连接

调用webshot()后,筛选出所有处于打开状态的FIFO连接并关闭:

# 定义清理函数
close_fifo_conns <- function() {
  # 获取所有连接信息
  conn_list <- showConnections(all = TRUE)
  # 筛选出打开的FIFO连接下标
  fifo_indices <- which(conn_list$class == "fifo" & conn_list$isopen)
  # 逐个关闭连接
  if (length(fifo_indices) > 0) {
    invisible(lapply(fifo_indices, function(i) close(getConnection(i))))
  }
}

# 使用示例
Sys.setenv(OPENSSL_CONF = "/dev/null")
webshot::webshot("https://github.com/rstudio/shiny")
Sys.unsetenv(OPENSSL_CONF)
close_fifo_conns()

2. 在包函数中自动执行关闭逻辑

借助withr::defer(),确保无论函数是否正常执行,都会在退出时关闭连接,适合包内函数使用:

my_screenshot <- function(url, ...) {
  # 注册退出时自动执行的清理逻辑
  withr::defer(close_fifo_conns())
  
  # 执行截图操作
  Sys.setenv(OPENSSL_CONF = "/dev/null") # 按需添加
  result <- webshot::webshot(url, ...)
  Sys.unsetenv(OPENSSL_CONF) # 按需添加
  
  return(result)
}

# 配套的清理函数
close_fifo_conns <- function() {
  conn_list <- showConnections(all = TRUE)
  fifo_indices <- which(conn_list$class == "fifo" & conn_list$isopen)
  if (length(fifo_indices) > 0) {
    invisible(lapply(fifo_indices, function(i) close(getConnection(i))))
  }
}

3. 迁移至webshot2(推荐)

webshot2是webshot的官方替代版本,使用Chrome/Chromium而非PhantomJS作为引擎,从根本上避免了FIFO连接遗留问题,同时支持更多现代网页特性。只需替换包依赖与函数调用:

# 安装webshot2
install.packages("webshot2")

# 替换原有调用
webshot2::webshot("https://github.com/rstudio/shiny")

内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 02:37:08