Skip to content

Instantly share code, notes, and snippets.

@aslushnikov
Last active July 17, 2020 19:20
Show Gist options
  • Save aslushnikov/2766200430228c3700537292fccad064 to your computer and use it in GitHub Desktop.
Save aslushnikov/2766200430228c3700537292fccad064 to your computer and use it in GitHub Desktop.

What is this for

This script lists the package names for the missing libraries in a given debian distribution.

Usage

Using the script (e.g. with ubuntu 18.04)

  1. Put script in the current directory and name it deps.js
  2. Run docker with distro in question and mount current folder with the script into it
$ docker run -v $PWD:/root/hostfolder --rm -it ubuntu:bionic /bin/bash

NOTE all the following steps happen inside docker container.

  1. Install node.js and npm:
$ apt-get update && apt-get install -y curl && \
    curl -sL https://deb.nodesource.com/setup_12.x | bash - && \
    apt-get install -y nodejs
  1. Install apt-file and update it:
$ apt-get update && apt-get install -y apt-file && apt-file update
  1. Make folder and download Playwright browsers:
$ mkdir /root/tmp && cd /root/tmp && npm init -y && npm i playwright
  1. Copy the deps.js in the tmp folder and run it:
$ cp /root/hostfolder/deps.js . && node deps.js
#!/usr/bin/env node
const fs = require('fs');
const util = require('util');
const path = require('path');
const {spawn} = require('child_process');
const browserPaths = require('playwright/lib/install/browserPaths.js');
(async () => {
const allBrowsersPath = browserPaths.browsersPath();
const {stdout} = await runCommand('find', [allBrowsersPath, '-executable', '-type', 'f']);
const lddPaths = stdout.split('\n').map(f => f.trim()).filter(filePath => !filePath.toLowerCase().endsWith('.sh'));
const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath)));
const missingDeps = new Set();
for (const deps of allMissingDeps) {
for (const dep of deps)
missingDeps.add(dep);
}
console.log([...missingDeps].sort());
for (const dep of missingDeps) {
const packages = await findPackages(dep);
if (packages.length === 0)
console.log(`${dep} => MISSING`);
else if (packages.length === 1)
console.log(`${dep} => ${packages[0]}`);
else
console.log(`${dep} => ${JSON.stringify(packages)}`);
}
})();
async function findPackages(libraryName) {
const {stdout} = await runCommand('apt-file', ['search', libraryName]);
const libs = stdout.trim().split('\n').map(line => line.split(':')[0]);
return [...new Set(libs)];
}
async function fileDependencies(filePath) {
const {stdout} = await lddAsync(filePath);
const deps = stdout.split('\n').map(line => {
line = line.trim();
const missing = line.includes('not found');
const name = line.split('=>')[0].trim();
return {name, missing};
});
return deps;
}
async function missingFileDependencies(filePath) {
const deps = await fileDependencies(filePath);
return deps.filter(dep => dep.missing).map(dep => dep.name);
}
async function lddAsync(filePath) {
return await runCommand('ldd', [filePath], {
cwd: path.dirname(filePath),
env: {
...process.env,
LD_LIBRARY_PATH: path.dirname(filePath),
},
});
}
function runCommand(command, args, options = {}) {
const childProcess = spawn(command, args, options);
return new Promise((resolve) => {
let stdout = '';
let stderr = '';
childProcess.stdout.on('data', data => stdout += data);
childProcess.stderr.on('data', data => stderr += data);
childProcess.on('close', (code) => {
resolve({stdout, stderr, code});
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment