admina
Version:
Detect root/admin/sudo and execute commands as it if available
89 lines • 9.78 kB
JavaScript
import which from "which";
import { execa, execaCommand, execaCommandSync, execaSync, } from "execa";
/** Detect if sudo is available */
export function hasSudo() {
return which.sync("sudo", { nothrow: true }) !== null;
}
/**
* Detect if the process has root privilege on Posix.
*
* @example
*
* ```js
* import { isRoot } from "admina"
*
* console.log(isRoot())
* //=> false
* ```
*
* @returns Whether the process is running as root.
*/
export function isRoot() {
// TODO not all CI systems are root
return process.getuid?.() === 0 || Boolean(process.env.CI);
}
/** Detect if sudo is available and the user has root privileges */
export function isSudo() {
return isRoot() && hasSudo();
}
/** Prepend `sudo` to the command if sudo is available */
export function prependSudo(command) {
if (isSudo()) {
return `sudo ${command}`;
}
return command;
}
/** Default exec options `{ stdio: "inherit", shell: true }` */
export const defaultExecOptions = {
stdio: "inherit",
shell: true,
};
/**
* Execute a command as root if sudo is available. Otherwise executes the command normally without sudo.
*
* @param program The program to spawn
* @param args The command arguments
* @param execOptions The options passed to `execa`. Defaults to `{ stdio: "inherit", shell: true }`
* @returns The execution result
*/
export function execRootSync(program, args = [], execOptions = defaultExecOptions) {
if (isSudo()) {
const command = getSudoCommand(program, args);
return execaCommandSync(command, execOptions);
}
else {
return execaSync(program, args, execOptions);
}
}
/**
* Asynchronously execute a command as root if sudo is available. Otherwise executes the command normally without sudo.
*
* @param program The program to spawn
* @param args The command arguments
* @param execOptions The options passed to `execa`. Defaults to `{ stdio: "inherit", shell: true }`
* @returns A promise to the execution result
*/
export function execRoot(program, args = [], execOptions = defaultExecOptions) {
if (isSudo()) {
const command = getSudoCommand(program, args);
return execaCommand(command, execOptions);
}
else {
return execa(program, args, execOptions);
}
}
function getSudoCommand(program, args) {
return `sudo ${quote([program, ...args]).join(" ")}`;
}
function quote(strings) {
return strings.map((str) => (isQuoted(str) ? str : `'${str}'`));
}
function isQuoted(str) {
if (str.length < 2) {
return false;
}
const first = str[0];
const last = str[str.length - 1];
return (first === "'" && last === "'") || (first === '"' && last === '"');
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9vdC5tanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcm9vdC5tdHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFBO0FBQ3pCLE9BQU8sRUFDTCxLQUFLLEVBQ0wsWUFBWSxFQUNaLGdCQUFnQixFQUNoQixTQUFTLEdBS1YsTUFBTSxPQUFPLENBQUE7QUFFZCxrQ0FBa0M7QUFDbEMsTUFBTSxVQUFVLE9BQU87SUFDckIsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxLQUFLLElBQUksQ0FBQTtBQUN2RCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxNQUFNO0lBQ3BCLG1DQUFtQztJQUNuQyxPQUFPLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUM1RCxDQUFDO0FBRUQsbUVBQW1FO0FBQ25FLE1BQU0sVUFBVSxNQUFNO0lBQ3BCLE9BQU8sTUFBTSxFQUFFLElBQUksT0FBTyxFQUFFLENBQUE7QUFDOUIsQ0FBQztBQUVELHlEQUF5RDtBQUN6RCxNQUFNLFVBQVUsV0FBVyxDQUFDLE9BQWU7SUFDekMsSUFBSSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ2IsT0FBTyxRQUFRLE9BQU8sRUFBRSxDQUFBO0lBQzFCLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQTtBQUNoQixDQUFDO0FBRUQsK0RBQStEO0FBQy9ELE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFxQjtJQUNsRCxLQUFLLEVBQUUsU0FBUztJQUNoQixLQUFLLEVBQUUsSUFBSTtDQUNaLENBQUE7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FDMUIsT0FBZSxFQUNmLE9BQWlCLEVBQUUsRUFDbkIsY0FBZ0Msa0JBQWtCO0lBRWxELElBQUksTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNiLE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDN0MsT0FBTyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFDL0MsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFBO0lBQzlDLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxRQUFRLENBQ3RCLE9BQWUsRUFDZixPQUFpQixFQUFFLEVBQ25CLGNBQTRCLGtCQUFrQjtJQUU5QyxJQUFJLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDYixNQUFNLE9BQU8sR0FBRyxjQUFjLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzdDLE9BQU8sWUFBWSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQTtJQUMzQyxDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFDMUMsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxPQUFlLEVBQUUsSUFBYztJQUNyRCxPQUFPLFFBQVEsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQTtBQUN0RCxDQUFDO0FBRUQsU0FBUyxLQUFLLENBQUMsT0FBaUI7SUFDOUIsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQTtBQUNqRSxDQUFDO0FBRUQsU0FBUyxRQUFRLENBQUMsR0FBVztJQUMzQixJQUFJLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbkIsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3BCLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFBO0lBQ2hDLE9BQU8sQ0FBQyxLQUFLLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxHQUFHLElBQUksSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFBO0FBQzNFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgd2hpY2ggZnJvbSBcIndoaWNoXCJcbmltcG9ydCB7XG4gIGV4ZWNhLFxuICBleGVjYUNvbW1hbmQsXG4gIGV4ZWNhQ29tbWFuZFN5bmMsXG4gIGV4ZWNhU3luYyxcbiAgdHlwZSBTeW5jT3B0aW9ucyBhcyBFeGVjYVN5bmNPcHRpb25zLFxuICB0eXBlIEV4ZWNhU3luY1JldHVyblZhbHVlLFxuICB0eXBlIE9wdGlvbnMgYXMgRXhlY2FPcHRpb25zLFxuICB0eXBlIEV4ZWNhQ2hpbGRQcm9jZXNzLFxufSBmcm9tIFwiZXhlY2FcIlxuXG4vKiogRGV0ZWN0IGlmIHN1ZG8gaXMgYXZhaWxhYmxlICovXG5leHBvcnQgZnVuY3Rpb24gaGFzU3VkbygpOiBib29sZWFuIHtcbiAgcmV0dXJuIHdoaWNoLnN5bmMoXCJzdWRvXCIsIHsgbm90aHJvdzogdHJ1ZSB9KSAhPT0gbnVsbFxufVxuXG4vKipcbiAqIERldGVjdCBpZiB0aGUgcHJvY2VzcyBoYXMgcm9vdCBwcml2aWxlZ2Ugb24gUG9zaXguXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogaW1wb3J0IHsgaXNSb290IH0gZnJvbSBcImFkbWluYVwiXG4gKlxuICogY29uc29sZS5sb2coaXNSb290KCkpXG4gKiAvLz0+IGZhbHNlXG4gKiBgYGBcbiAqXG4gKiBAcmV0dXJucyBXaGV0aGVyIHRoZSBwcm9jZXNzIGlzIHJ1bm5pbmcgYXMgcm9vdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUm9vdCgpOiBib29sZWFuIHtcbiAgLy8gVE9ETyBub3QgYWxsIENJIHN5c3RlbXMgYXJlIHJvb3RcbiAgcmV0dXJuIHByb2Nlc3MuZ2V0dWlkPy4oKSA9PT0gMCB8fCBCb29sZWFuKHByb2Nlc3MuZW52LkNJKVxufVxuXG4vKiogRGV0ZWN0IGlmIHN1ZG8gaXMgYXZhaWxhYmxlIGFuZCB0aGUgdXNlciBoYXMgcm9vdCBwcml2aWxlZ2VzICovXG5leHBvcnQgZnVuY3Rpb24gaXNTdWRvKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNSb290KCkgJiYgaGFzU3VkbygpXG59XG5cbi8qKiBQcmVwZW5kIGBzdWRvYCB0byB0aGUgY29tbWFuZCBpZiBzdWRvIGlzIGF2YWlsYWJsZSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZXBlbmRTdWRvKGNvbW1hbmQ6IHN0cmluZykge1xuICBpZiAoaXNTdWRvKCkpIHtcbiAgICByZXR1cm4gYHN1ZG8gJHtjb21tYW5kfWBcbiAgfVxuICByZXR1cm4gY29tbWFuZFxufVxuXG4vKiogRGVmYXVsdCBleGVjIG9wdGlvbnMgYHsgc3RkaW86IFwiaW5oZXJpdFwiLCBzaGVsbDogdHJ1ZSB9YCAqL1xuZXhwb3J0IGNvbnN0IGRlZmF1bHRFeGVjT3B0aW9uczogRXhlY2FTeW5jT3B0aW9ucyA9IHtcbiAgc3RkaW86IFwiaW5oZXJpdFwiLFxuICBzaGVsbDogdHJ1ZSxcbn1cblxuLyoqXG4gKiBFeGVjdXRlIGEgY29tbWFuZCBhcyByb290IGlmIHN1ZG8gaXMgYXZhaWxhYmxlLiBPdGhlcndpc2UgZXhlY3V0ZXMgdGhlIGNvbW1hbmQgbm9ybWFsbHkgd2l0aG91dCBzdWRvLlxuICpcbiAqIEBwYXJhbSBwcm9ncmFtIFRoZSBwcm9ncmFtIHRvIHNwYXduXG4gKiBAcGFyYW0gYXJncyBUaGUgY29tbWFuZCBhcmd1bWVudHNcbiAqIEBwYXJhbSBleGVjT3B0aW9ucyBUaGUgb3B0aW9ucyBwYXNzZWQgdG8gYGV4ZWNhYC4gRGVmYXVsdHMgdG8gYHsgc3RkaW86IFwiaW5oZXJpdFwiLCBzaGVsbDogdHJ1ZSB9YFxuICogQHJldHVybnMgVGhlIGV4ZWN1dGlvbiByZXN1bHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4ZWNSb290U3luYyhcbiAgcHJvZ3JhbTogc3RyaW5nLFxuICBhcmdzOiBzdHJpbmdbXSA9IFtdLFxuICBleGVjT3B0aW9uczogRXhlY2FTeW5jT3B0aW9ucyA9IGRlZmF1bHRFeGVjT3B0aW9ucyxcbik6IEV4ZWNhU3luY1JldHVyblZhbHVlPHN0cmluZz4ge1xuICBpZiAoaXNTdWRvKCkpIHtcbiAgICBjb25zdCBjb21tYW5kID0gZ2V0U3Vkb0NvbW1hbmQocHJvZ3JhbSwgYXJncylcbiAgICByZXR1cm4gZXhlY2FDb21tYW5kU3luYyhjb21tYW5kLCBleGVjT3B0aW9ucylcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZXhlY2FTeW5jKHByb2dyYW0sIGFyZ3MsIGV4ZWNPcHRpb25zKVxuICB9XG59XG5cbi8qKlxuICogQXN5bmNocm9ub3VzbHkgZXhlY3V0ZSBhIGNvbW1hbmQgYXMgcm9vdCBpZiBzdWRvIGlzIGF2YWlsYWJsZS4gT3RoZXJ3aXNlIGV4ZWN1dGVzIHRoZSBjb21tYW5kIG5vcm1hbGx5IHdpdGhvdXQgc3Vkby5cbiAqXG4gKiBAcGFyYW0gcHJvZ3JhbSBUaGUgcHJvZ3JhbSB0byBzcGF3blxuICogQHBhcmFtIGFyZ3MgVGhlIGNvbW1hbmQgYXJndW1lbnRzXG4gKiBAcGFyYW0gZXhlY09wdGlvbnMgVGhlIG9wdGlvbnMgcGFzc2VkIHRvIGBleGVjYWAuIERlZmF1bHRzIHRvIGB7IHN0ZGlvOiBcImluaGVyaXRcIiwgc2hlbGw6IHRydWUgfWBcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0byB0aGUgZXhlY3V0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXhlY1Jvb3QoXG4gIHByb2dyYW06IHN0cmluZyxcbiAgYXJnczogc3RyaW5nW10gPSBbXSxcbiAgZXhlY09wdGlvbnM6IEV4ZWNhT3B0aW9ucyA9IGRlZmF1bHRFeGVjT3B0aW9ucyxcbik6IEV4ZWNhQ2hpbGRQcm9jZXNzPHN0cmluZz4ge1xuICBpZiAoaXNTdWRvKCkpIHtcbiAgICBjb25zdCBjb21tYW5kID0gZ2V0U3Vkb0NvbW1hbmQocHJvZ3JhbSwgYXJncylcbiAgICByZXR1cm4gZXhlY2FDb21tYW5kKGNvbW1hbmQsIGV4ZWNPcHRpb25zKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBleGVjYShwcm9ncmFtLCBhcmdzLCBleGVjT3B0aW9ucylcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTdWRvQ29tbWFuZChwcm9ncmFtOiBzdHJpbmcsIGFyZ3M6IHN0cmluZ1tdKSB7XG4gIHJldHVybiBgc3VkbyAke3F1b3RlKFtwcm9ncmFtLCAuLi5hcmdzXSkuam9pbihcIiBcIil9YFxufVxuXG5mdW5jdGlvbiBxdW90ZShzdHJpbmdzOiBzdHJpbmdbXSkge1xuICByZXR1cm4gc3RyaW5ncy5tYXAoKHN0cikgPT4gKGlzUXVvdGVkKHN0cikgPyBzdHIgOiBgJyR7c3RyfSdgKSlcbn1cblxuZnVuY3Rpb24gaXNRdW90ZWQoc3RyOiBzdHJpbmcpIHtcbiAgaWYgKHN0ci5sZW5ndGggPCAyKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgY29uc3QgZmlyc3QgPSBzdHJbMF1cbiAgY29uc3QgbGFzdCA9IHN0cltzdHIubGVuZ3RoIC0gMV1cbiAgcmV0dXJuIChmaXJzdCA9PT0gXCInXCIgJiYgbGFzdCA9PT0gXCInXCIpIHx8IChmaXJzdCA9PT0gJ1wiJyAmJiBsYXN0ID09PSAnXCInKVxufVxuIl19