如何在node.js中检查文件是否可执行?

12

如何在node.js中检查文件是否可执行?

可能像这样:

fs.isExecutable(function (isExecutable) {

})
6个回答

19

仅依赖于内置fs模块的另一种选择是使用 fs.accessfs.accessSync。这种方法比获取和解析文件模式更容易。例如:

const fs = require('fs');

fs.access('./foobar.sh', fs.constants.X_OK, (err) => {
    console.log(err ? 'cannot execute' : 'can execute');
});

读/写,还是执行?我们需要能够执行该文件。 - Alexander Mills
好的,我更新了示例以匹配具体问题。 - Danny Guo

9
你需要使用fs.stat调用来完成这项任务。 fs.stat调用返回一个fs.Stats对象。
在该对象中,有一个mode属性。该属性将告诉你文件是否可执行。
在我的情况下,我创建了一个文件并使用chmod 755 test_file,然后运行了以下代码:
var fs = require('fs');
test = fs.statSync('test_file');
console.log(test);

我得到的 test.mode 值为 33261。

这个链接 对于将 mode 转换为 Unix 文件权限等价物非常有帮助。


还有一个非常有帮助的模块mode-to-permissions,如果您不想处理细节。 - tomekwi
如果它解释了如何确定给定模式的文件是否可执行,那么我会点赞这个。 - Alexander Mills
他们后来在stdlib中添加了常量,例如fs.constants.S_IXUSR。顺便说一句:https://dev59.com/KmQo5IYBdhLWcg3wKs1r#69897809 - Ciro Santilli OurBigBook.com

3

fs.stat命名的按位掩码模式检查与fs.constants.S_IXUSR

https://dev59.com/KmQo5IYBdhLWcg3wKs1r#16258627编写以来,Node.js似乎已添加了这些内容,现在可以执行以下操作:

const fs = require('fs');

function isExec(p) {
  return !!(fs.statSync(p).mode & fs.constants.S_IXUSR)
}

console.log(isExec('/usr/bin/ls'))
console.log(isExec('/dev/random'))

当然,这也凸显了一个事实,即实际执行“我能执行这个文件检查”有点困难,因为我们有三个常量如https://nodejs.org/docs/latest-v17.x/api/fs.html#file-mode-constants所述:
  • fs.constants.S_IXUSR:用户
  • fs.constants.S_IXGRP:组
  • fs.constants.S_IXOTH:其他人
如下所示:
man 2 chmod

因此,使用stat进行完整检查需要检查是否与文件所有者匹配或是否属于组。

因此,也许最好只使用fs.accessSync的繁琐API,如https://dev59.com/KmQo5IYBdhLWcg3wKs1r#41929624中所述:

const fs = require('fs');

function isExec(p) {
  try {
    fs.accessSync(p, fs.constants.X_OK)
    return true
  } catch (e) {
    return false
  }
}

console.log(isExec('/usr/bin/ls'))
console.log(isExec('/dev/random'))

这些检查应该由它自己来完成。


2

2
在Node中,fs.stat方法返回一个fs.Stats对象,您可以通过fs.Stats.mode属性获取文件权限。参考这篇文章:Nodejs文件权限

1
这个版本更加功能齐全,但需要依赖于操作系统特定的whichwhere命令。它支持Windows和Posix(Mac、Linux、Unix、如果Posix层暴露或安装了Posix工具,则也支持Windows)。
const fs = require('fs');
const path = require('path');
const child = require("child_process");

function getExecPath(exec) {
  let result;
  try {
    result = child.execSync("which " + exec).toString().trim();
  } catch(ex) {
    try {
      result = child.execSync("where " + exec).toString().trim();
    } catch(ex2) {
      return;
    }
  }
  if (result.toLowerCase().indexOf("command not found") !== -1 ||
      result.toLowerCase().indexOf("could not find files") !== -1) {
    return;
  }
  return result;
}    


function isExec(exec) {
  if (process.platform === "win32") {
    switch(Path.GetExtension(exec).toLowerCase()) {
      case "exe": case "bat": case "cmd": case "vbs": case "ps1": {
        return true;
      }
    }
  }
  try {
    // Check if linux has execution rights
    fs.accessSync(exec, fs.constants.X_OK);
    return true;
  } catch(ex) {
  }
  // Exists on the system path
  return typeof(getExecPath(exec)) !== 'undefined';
}

那个 child.execSync 调用对我来说看起来不安全,攻击者肯定可以提供一个值给 exec,从而允许它在你的电脑上执行任意代码。这是不可取的。还有其他检查方法吗? - Fabio Spampinato
是的,这种级别的卫生应该在您的 REST 端点或任何机制被调用之前发生。否则,攻击者将可以访问命令提示符。而且,在使用 node 调用此脚本之前无需查找它。还要注意:这可能更倾向于 Node 的早期版本。Deno(Node 替代品)有更简单、更安全的方法来实现这一点。 - TamusJRoyce

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