.gitignore000066400000000000000000000004131516157350500130540ustar00rootroot00000000000000/build /node_modules /*.log /generated /ramdisk-settings.json .idea/workspace.xml .idea/tasks.xml .idea/profiles_settings.xml .idea/inspectionProfiles/Project_Default.xml .idea/inspectionProfiles/profiles_settings.xml node_modules/.yarn-integrity package-lock.json .idea/000077500000000000000000000000001516157350500120465ustar00rootroot00000000000000.idea/codeStyleSettings.xml000066400000000000000000000004251516157350500162450ustar00rootroot00000000000000 .idea/modules.xml000066400000000000000000000004121516157350500142350ustar00rootroot00000000000000 .idea/ramdisk.iml000066400000000000000000000005201516157350500142000ustar00rootroot00000000000000 .idea/vcs.xml000066400000000000000000000002471516157350500133660ustar00rootroot00000000000000 .npmignore000066400000000000000000000002221516157350500130610ustar00rootroot00000000000000/.idea /artifacts /build /test /node_modules /*.iml /*.ipr /*.iws /.travis.yml /.scrutinizer.yml /Gruntfile.js /*.lock *.log /corifeus-boot.json .scrutinizer.yml000066400000000000000000000020231516157350500142450ustar00rootroot00000000000000checks: javascript: true filter: excluded_paths: - test/* - node_modules/* - build/* - docs/* build: cache: disabled: true environment: google_chrome: use_latest: true variables: CXX: g++-4.8 dependencies: before: - export LATEST=$(nvm ls-remote | tail -1) - nvm install $LATEST # - nvm use $LATEST - sudo apt-get -y install software-properties-common python-software-properties # - sudo apt-cache policy gcc++ # - sudo apt-cache policy g++ # - sudo apt update -y - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt update -y - sudo apt-get install -y gcc-4.8 - sudo apt-get install -y g++-4.8 - sudo apt-get install -y libglib2.0-dev - npm install -g node-gyp - npm install -g grunt-cli - git config remote.origin.url - node -v tests: override: - command: 'grunt' coverage: file: 'build/coverage/clover.xml' format: 'clover' .travis.yml000066400000000000000000000004421516157350500131770ustar00rootroot00000000000000language: node_js sudo: required node_js: - "node" env: - CXX=g++-4.8 addons: apt: sources: - ubuntu-toolchain-r-test packages: - dbus - gcc-4.8 - g++-4.8 - libglib2.0-dev before_script: - npm install -g node-gyp - npm install grunt-cli -g Gruntfile.js000066400000000000000000000007471516157350500133730ustar00rootroot00000000000000module.exports = (grunt) => { const builder = require(`corifeus-builder`); const loader = new builder.loader(grunt); loader.js({ replacer: { type: 'p3x', npmio: true, }, config: { 'clean': { 'generated': [ 'generated' ] } } }); const defaults = [] grunt.registerTask('default', defaults.concat(builder.config.task.build.js)); } LICENSE000066400000000000000000000021411516157350500120710ustar00rootroot00000000000000MIT License Copyright (c) 2018 Patrik Laszlo / patrikx3 / https://patrikx3.com and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. README.md000066400000000000000000000252701516157350500123530ustar00rootroot00000000000000[//]: #@corifeus-header [![Build Status](https://travis-ci.org/patrikx3/ramdisk.svg?branch=master)](https://travis-ci.org/patrikx3/ramdisk) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/patrikx3/ramdisk/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/patrikx3/ramdisk/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/patrikx3/ramdisk/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/patrikx3/ramdisk/?branch=master) [![NPM](https://nodei.co/npm/p3x-ramdisk.png?downloads=true&downloadRank=true&stars=true)](https://www.npmjs.com/package/p3x-ramdisk/) --- # RAM disk persistent with Systemd timer, service and suspend v1.0.574-260 This is an open source project. Just code. If you like this code, please add a star in GitHub and you really like, you can donate as well. Thanks you so much! Given, I have my own server, with dynamic IP address, it could happen that the server for about max 5 minutes can not be reachable for the dynamic DNS or very rarely I backup with Clonzilla the SSD or something with the electricity (too much hoovering or cleaning - but I worked on it, so should not happen again), but for some reason, it is not reachable please hang on for 5-30 minutes and it will be back for sure. All my domains (patrikx3.com and corifeus.com) could have errors right now, since I am developing in my free time and you can catch glitches, but usually it is stable (imagine updating everything always, which is weird). ### Node Version Requirement ``` >=8.9.0 ``` ### Built on Node ``` v9.5.0 ``` The ```async``` and ```await``` keywords are required. Install NodeJs: https://nodejs.org/en/download/package-manager/ # Description [//]: #@corifeus-header:end # Install ```bash sudo npm install -g p3x-ramdisk --unsafe-perm=true --allow-root ``` ## IntelliJ Speed Based on: http://sheroz.com/pages/blog/improving-development-performance-moving-intellij-idea-cache-ramdisk.html ```text After all these tricks I tried to open my current project with IntelliJ IDEA 12 … Wow!!! It is fantastic! Works like a … sword!!! Why sword?! I don’t know exactly. May be because of Darcula theme. This is just first thought what came to my mind seeing the overall results. The Intellij IDEA 12 now works as a lightsaber sword, as a weapon of a Jedi Knight, which you can trust in Java world! ``` * Requires tmpfs, bash, fstab, rsync, memory :) * Usually, all requirements of every Unix flavor are installed by default * SystemD * Service * Timer * Suspend * RAM disk to HDD * Linux, Unix, BSD, macOS * Should might need some tuning, but the functions are there, I just only tested in Linux. ## Intel Optane I think my ramdisk is faster. :) Ciao!!! # Use case Speed up IntelliJ and development Node. (Tons of files.) The result is that the development is many folds faster. No waiting at all. # Install ```text patrikx3@workstation ~ $ p3x-ramdisk install --help Usage: install [options] Install a p3x-ramdisk Options: -h, --help output usage information -r, --rampath [path] The path of the ram disk, default /home/$USERNAME/ramdisk -p, --persistent [path] The path of the ram persistent, default /home/$USERNAME/ramdisk-persistent -g, --gid [group] The gid, it you omit it is the current user -t, --timer [minutes] The timer in minutes, minimum about 10 minutes, Default is 20 minutes, the best -s, --size [megabytes] Ramdisk in size of megabytes, default is 4096 megabytes ``` # IMPORTANT Trash is disabled in GNOME with p3x-ramdisk. It will ask for confirm to delete data. You might have it in the previous save. It is possible to enable trash bin, but for me is not important now, so I disabled, memory is not cheap. # Setup **Use GitHub for info, NPM hides wide strings.** https://github.com/patrikx3/ramdisk ```bash # of course your data will never be deleted, # double persistence (current, previouse, saves every 20 minutes) # load on boot, plus at shutdown and suspend it saves sudo npm install -g p3x-ramdisk --unsafe-perm=true --allow-root # install # if you need less/more memory, add -s 1024 or even more, 10GB is good :) sudo p3x-ramdisk install $USERNAME # Get the output, add to /etc/fstab echo "tmpfs /home/patrikx3/ramdisk tmpfs gid=10000,uid=10000,size=4096M 0 0" | sudo tee -a /etc/fstab sudo mount -a # you should verify the ramdisk is existing now, you might have to reboot # on linux it can show your settings, like below: df -h # if there is an error, you can sudo p3x-ramdisk stop # if all good # STARTUP THE RAMDISK PERSISTENT sudo p3x-ramdisk start # you can work like here # /home/$USERNAME/ramdisk/persistence/content # SOME DEBUG p3x-ramdisk watch # to trigger a savs p3x-ramdisk save # you don't need usually to save # the default is 20 minutes # the systemd service saves on suspend and shutdown # to stop the services # removes sync, so the ramdisk files will be unavailable, # only be in /home/username/ramdisk-persistent/current sudo p3x-ramdisk stop # your duplicate copies are ls -all /home/$USERNAME/ramdisk-persistent/current/ ls -all /home/$USERNAME/ramdisk-persistent/previous/ # you are done # the default use case is to speed up working with IntelliJ and my projects to ramdisk # if you just want persistent folder and that's all # there is a special folder, .p3x-ramdisk-link # everything there is linked into /home/$USERNAME # if there is nothing in .p3x-ramdisk-link # no linking is. to test it, you might not need it. ``` ## Linkin' in /home ```bash ### //LINKING:START # LINKING - IS NOT REQUIRED, but is good as a sword :) p3x-ramdisk save sudo p3x-ramdisk stop mkdir -p /home/$USERNAME/ramdisk-persistent/current/.p3x-ramdisk-link cp -avr /home/$USERNAME/.IntelliJIdea2017.3 /home/$USERNAME/ramdisk-persistent/current/.p3x-ramdisk-link # backup mkdir -p /home/$USERNAME/backup mv /home/$USERNAME/.IntelliJIdea2017.3 /home/username/backup/ # need to delete the originals, since they become symlinks rm -rf /home/$USERNAME/.IntelliJIdea2017.3 sudo p3x-ramdisk start ### //LINKING:END ``` # Output ## Install ```text patrikx3@laptop:~/ramdisk/persistence/content/.p3x-ramdisk-link/Projects/patrikx3/ramdisk$ sudo p3x-ramdisk install patrikx3 -s 6144 2017-05-08 00:30:08: terminal install 2017-05-08 00:30:08: terminal copy 2017-05-08 00:30:08: terminal suspend 2017-05-08 00:30:08: terminal reload services 2017-05-08 00:30:08: terminal install done Settings: { "rampath": "ramdisk", "persistent": "ramdisk-persistent", "uid": "patrikx3", "uidNumber": 10000, "gid": "patrikx3", "timer": 20, "size": "4096", "home": "/home/patrikx3", "script": "/home/patrikx3/.p3x-ramdisk" } Final commands: -------------------------- 1) You only have to do it once, if you haven't done it before echo "tmpfs /home/patrikx3/ramdisk tmpfs gid=10000,uid=10000,size=4096M 0 0" | sudo tee -a /etc/fstab sudo mount -a -------------------------- 2) verify that ramdisk is working, see it here df -h -------------------------- 3) if everything is ok, start the persistent ramdisk sudo p3x-ramdisk start patrikx3@laptop:~/ramdisk/persistence/content/.p3x-ramdisk-link/Projects/patrikx3/ramdisk$ ``` ## Watching the RAM disk ```bash p3x-ramdisk watch ``` ``` Filesystem Size Used Avail Use% Mounted on tmpfs 4,0G 2,0G 2,1G 50% /home/patrikx3/ramdisk total used free shared buff/cache available Mem: 31G 3,3G 18G 2,0G 9,8G 25G Swap: 8,0G 0B 8,0G Load: 2017-05-27 09:01:49 2017-05-27 09:01:56 0 minutes 7 seconds Save: 2017-05-27 09:20:00 2017-05-27 09:20:16 0 minutes 16 seconds 2017-05-27 09:20:00: timer save, ramdisk to current 2017-05-27 09:20:00: timer save /home/patrikx3/ramdisk/persistence/content to /home/patrikx3/ramdisk-persistent/current 2017-05-27 09:20:16: timer saved 2017-05-27 09:20:16: timer save done 2017-05-27 09:20:16: timer 0 minutes 16 seconds 5/27/2017, 9:24:45 AM | Persistence 20 minutes | Watch 1 second ``` # LOGS ``` /home/username/ramdisk-persistent/ramdisk-persistent.log ``` ``` /home/username/ramdisk-persistent/update-at-load.log ``` ``` /home/username/ramdisk-persistent/update-at-save.log ``` ## LOG info ```text 2017-05-06 02:57:37: boot loading 2017-05-06 02:57:37: boot load /home/patrikx3/ramdisk-persistent/current to /home/patrikx3/ramdisk/persistence/content 2017-05-06 02:57:47: boot loaded 2017-05-06 02:57:47: boot link 2017-05-06 02:57:47: boot link /home/patrikx3/ramdisk/persistence/content/.IntelliJIdea2017.3 to /home/patrikx3/.IntelliJIdea2017.3 2017-05-06 02:57:47: boot link /home/patrikx3/ramdisk/persistence/content/Projects to /home/patrikx3/Projects 2017-05-06 02:57:47: boot link done 2017-05-06 02:57:47: boot 0 minutes 10 seconds 2017-05-06 02:57:47: timer save 2017-05-06 02:57:47: timer save, current to previous 2017-05-06 02:57:47: timer save /home/patrikx3/ramdisk-persistent/current to /home/patrikx3/ramdisk-persistent/previous 2017-05-06 02:57:50: timer saved 2017-05-06 02:57:50: timer save, ramdisk to current 2017-05-06 02:57:50: timer save /home/patrikx3/ramdisk/persistence/content to /home/patrikx3/ramdisk-persistent/current 2017-05-06 02:57:53: timer saved 2017-05-06 02:57:53: timer save done 2017-05-06 02:57:53: timer 0 minutes 6 seconds ``` ## LOG Update ```text 2017-05-06 03:31:51 2017-05-06 03:31:57 0 minutes 6 seconds ``` # Thunder ramdisk persistence ```text patrikx3@workstation ~/ramdisk-persistent/current/.p3x-ramdisk-link $ ll total 32 drwxr-xr-x 8 patrikx3 patrikx3 4096 May 7 13:04 ./ drwxr-xr-x 3 patrikx3 patrikx3 4096 May 7 13:02 ../ drwxr-xr-x 4 patrikx3 patrikx3 4096 Apr 25 17:51 .IntelliJIdea2017.3/ patrikx3@workstation ~/ramdisk-persistent/current/.p3x-ramdisk-link $ ``` [//]: #@corifeus-footer --- [**P3X-RAMDISK**](https://pages.corifeus.com/ramdisk) Build v1.0.574-260 [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=LFRV89WPRMMVE&lc=HU&item_name=Patrik%20Laszlo&item_number=patrikx3¤cy_code=HUF&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) ## Sponsor [![JetBrains](https://www.patrikx3.com/images/jetbrains-logo.svg)](https://www.jetbrains.com/) [//]: #@corifeus-footer:end bin/000077500000000000000000000000001516157350500116365ustar00rootroot00000000000000bin/p3x-ramdisk.js000077500000000000000000000020471516157350500143440ustar00rootroot00000000000000#!/usr/bin/env node if (!require('fs').existsSync(`${__dirname}/../node_modules`)) { require('child_process').execSync(`cd ${__dirname}/..; npm install`, { stdio: 'inherit' }); } const commander = require('commander'); const utils = require('corifeus-utils'); const pkg = require('../package.json'); const mz = require('mz'); const start = async() => { // command // required // [command] optional // [command ...] variable options commander .version(pkg.version) .usage('[command]') .action((command, options) => { console.error(`unknown command: ${command}`) }) ; require('../src/command/install') require('../src/command/start') require('../src/command/load') require('../src/command/watch') require('../src/command/save') require('../src/command/stop') require('../src/command/link') require('../src/command/status') commander.parse(process.argv); if (!process.argv.slice(2).length) { commander.outputHelp(); } } start();package.json000066400000000000000000000023361516157350500133600ustar00rootroot00000000000000{ "name": "p3x-ramdisk", "version": "1.0.574-260", "description": "RAM disk persistent with Systemd timer, service and suspend", "main": "Gruntfile.js", "corifeus": { "prefix": "p3x-", "type": "p3x", "publish": true, "code": "Vader", "nodejs": "v9.5.0" }, "bin": { "p3x-ramdisk": "bin/p3x-ramdisk.js" }, "scripts": { "test": "grunt " }, "repository": { "type": "git", "url": "git+https://github.com/patrikx3/ramdisk.git" }, "keywords": [ "linux", "systemd", "ramdisk", "ram", "disk", "suspend", "timer", "service", "unix", "bsd", "osx" ], "author": "Patrik Laszlo ", "license": "MIT", "bugs": { "url": "https://github.com/patrikx3/ramdisk/issues" }, "homepage": "https://pages.corifeus.com/ramdisk", "dependencies": { "clear": "^0.0.1", "commander": "^2.14.1", "corifeus-utils": "^1.1.824-287", "userid": "^0.3.1" }, "engines": { "node": ">=8.9.0" }, "devDependencies": { "corifeus-builder": "^1.7.1217-307" } }ramdisk.iml000066400000000000000000000005171516157350500132260ustar00rootroot00000000000000 src/000077500000000000000000000000001516157350500116555ustar00rootroot00000000000000src/command/000077500000000000000000000000001516157350500132735ustar00rootroot00000000000000src/command/install.js000066400000000000000000000022201516157350500152730ustar00rootroot00000000000000const commander = require('commander'); const ramdisk = require('../index'); // install commander .command('install ') .option('-r, --rampath [path]', 'The path of the ram disk, default /home/$USERNAME/ramdisk') .option('-p, --persistent [path]', 'The path of the ram persistent, default /home/$USERNAME/ramdisk-persistent') // .option('-u, --uid ', 'The username, it you omit it is the current user') .option('-g, --gid [group]', 'The gid, it you omit it is the current user') .option('-t, --timer [minutes]', 'The timer in minutes, minimum about 10 minutes, Default is 20 minutes, the best') .option('-s, --size [megabytes]', `Ramdisk in size of megabytes, default is ${ramdisk.defaults.ramdisk.size} megabytes`) // .option('-h, --home [type]', 'Home path, defaults to /home/uid') .description(` Install a p3x-ramdisk `) // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (uid, options) { try { await ramdisk.install(uid, options); } catch(e) { console.error(e); process.exit(1); } }) ; src/command/link.js000066400000000000000000000007171516157350500145730ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('link') .description(` Link from the ramdisk to the home `) // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (options) { const link = require('../index').link; try { await link(); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/command/load.js000066400000000000000000000007001516157350500145450ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('load') .description(` Load a p3x-ramdisk `) // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (options) { const load = require('../index').load; try { await load(); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/command/save.js000066400000000000000000000007021516157350500145660ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('save') .description(` Save the p3x-ramdisk `) // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (options) { const save = require('../index').save; try { await save(); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/command/start.js000066400000000000000000000007051516157350500147700ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('start') .description(` Start a p3x-ramdisk `) // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (options) { const start = require('../index').start; try { await start(); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/command/status.js000066400000000000000000000005751516157350500151630ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('status') .description(` Status of p3x-ramdisk `) .action(async function (options) { const status = require('../index').status; try { await status(options); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/command/stop.js000066400000000000000000000007031516157350500146160ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('stop') .description(` Stop a p3x-ramdisk `) // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (options) { const stop= require('../index').stop; try { await stop(); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/command/watch.js000066400000000000000000000010571516157350500147420ustar00rootroot00000000000000const commander = require('commander'); // install commander .command('watch') .description(` Watch the p3x-ramdisk `) .option('-w, --watch [milliseconds]', 'The time for watching, default is 1000 milliseconds') // .option('-d, --dry', 'Do not actually remove packages, just show what it does') .action(async function (options) { const watch = require('../index').watch; try { await watch(options); } catch(e) { console.error(e.message); process.exit(1); } }) ; src/index.js000066400000000000000000000160421516157350500133250ustar00rootroot00000000000000const mz = require('mz'); const path = require('path'); const utils = require('corifeus-utils'); const fsx = require('fs-extra'); const _ = require('lodash'); const clear = require('clear'); const ms = require('ms'); const settingsFile = `/etc/p3x-ramdisk.json`; const defaults = { ramdisk: { size: 2048, }, timer: { save: 20, } }; const requireRoot = () => { if (process.getuid && process.getuid() === 0) { return true; } throw new Error('you are not root! please sudo!') } const getGeneratedDir = (homedir = process.env.HOME) => { //return path.resolve(`${__dirname}/../generated`); return path.resolve(`${homedir}/.p3x-ramdisk`) } const getSettings = () => { const settings = require(settingsFile); settings.generatedDir = getGeneratedDir(settings.home); settings.program = `${path.resolve(settings.generatedDir )}/p3x-ramdisk.sh`; return settings; } const defaultTerminal= async (command, doesRequireRoot = false) => { if (doesRequireRoot ) { requireRoot(); } const settings = getSettings(); let commandExec = `${settings.program} ${command}`; await utils.childProcess.exec(commandExec, true) } const load = async() => { await defaultTerminal('load') } const link = async() => { await defaultTerminal('link') } const save = async() => { await defaultTerminal('save') } const status = async() => { requireRoot(); let commandExec = ` sudo service p3x-ramdisk status sudo systemctl status p3x-ramdisk-timer.timer `; await utils.childProcess.exec(commandExec, true) } const watch = async(options) => { const settings = getSettings(); options.watch = Number(options.watch) || 1000; const watch = ms(options.watch, { long: true }); const timer = ms(settings.timer * 1000 * 60, { long: true }); return new Promise(async () => { const show = async () => { const df = await utils.childProcess.exec(`df -h | grep -e ${settings.home}/${settings.rampath} -e Size`); const free = await utils.childProcess.exec(`free -h`); const loadLogFile = `${settings.home}/${settings.persistent}/update-at-load.log`; let loadLog; if (await mz.fs.exists(loadLogFile)) { loadLog = await mz.fs.readFile(loadLogFile); } else { loadLog = Promise.resolve('Load is not done.') } const saveLogFile = `${settings.home}/${settings.persistent}/update-at-save.log`; let saveLog; if (await mz.fs.exists(saveLogFile)) { saveLog = await mz.fs.readFile(saveLogFile); } else { saveLog = Promise.resolve('Save is not done.') } const logFile = `${settings.home}/${settings.persistent}/ramdisk-persistent.log`; let log; if (await mz.fs.exists(logFile)) { log = await utils.childProcess.exec(`tail -n 5 ${logFile}`); } else { log = Promise.resolve({ stdout: 'Log is not done.' }) } clear() console.log(`${df.stdout.trim()} ${free.stdout} Load: ${loadLog.toString().trim().split('\n').join(' ')} Save: ${saveLog.toString().trim().split('\n').join(' ')} ${log.stdout.trim()} ${new Date().toLocaleString()} | Persistence ${timer} | Watch ${watch}`); }; show(); setInterval(show, options.watch) }) } const start = async() => { await defaultTerminal('start', true) } const stop = async() => { await defaultTerminal('stop', true) } const install = async (uid, options) => { requireRoot(); // .option('-r, --rampath [type]', 'The path of the ram disk') // .option('-p, --persistent [type]', 'The path of the ram persistent') // .option('-u, --uid [type]', 'The username, it you omit it is the current user') // .option('-g, --gid [type]', 'The gid, it you omit it is the current user') // .option('-t, --timer [type]', 'The timer in minutes, minimum about 10 minutes, 20 is the best') // .option('-s, --size [type]', 'Ramdisk in size of MegaBYTEs, default is 8192') // .option('-h, --home [type]', 'Home path, defaults to /home/uid') // uid - current user default // gid - default uid // timer -- 20 min // rampath - default /home/uid/ramdisk // persistent - default /home/uid/ramdisk-persistent // home - default /home/uid/ // sciripts - is given const userid = require('userid'); const homedir = (await utils.childProcess.exec(`sudo -H -u ${uid} -i eval 'echo $HOME'`)).stdout.trim(); options = options || {}; const generateOptions = { rampath: options.rampath || 'ramdisk', persistent : options.persistent || 'ramdisk-persistent', uid : uid, uidNumber: userid.uid(uid), gidNumber: userid.gid(uid), gid : options.gid || uid, timer : options.timer || defaults.timer.save, size : options.size || defaults.ramdisk.size, home : homedir, } const generatedDir = getGeneratedDir(homedir) await fsx.emptyDir(generatedDir); generateOptions.script = generatedDir; const origin = `${__dirname}/../templates`; const files = await mz.fs.readdir(origin); _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; await utils.fs.ensureFile(settingsFile, JSON.stringify(generateOptions, null, 4), true ) await files.forEachAsync(async (file) => { const generatedFile = path.basename(file, '.hbs'); const buffer = await mz.fs.readFile(`${origin}/${file}`); const string = buffer.toString(); const generatedString = _.template(string)(generateOptions); await utils.fs.ensureFile(`${generatedDir}/${generatedFile}`, generatedString, true); }) const program = `${path.resolve(generateOptions.script)}/p3x-ramdisk.sh`; let command = `chown -R ${generateOptions.uidNumber}:${generateOptions.gidNumber} ${generatedDir} chmod u+x ${program} ${program} install `; //console.log(command) await utils.childProcess.exec(command, true) console.log(` Settings: ${JSON.stringify(generateOptions, null, 2)} Final commands: -------------------------- 1) You only have to do it once, if you haven't done it before echo "tmpfs ${generateOptions.home}/${generateOptions.rampath} tmpfs gid=${userid.gid(generateOptions.gid)},uid=${userid.uid(generateOptions.uid)},size=${generateOptions.size}M 0 0" | sudo tee -a /etc/fstab sudo mount -a -------------------------- 2) verify that ramdisk is working, see it here df -h -------------------------- 3) if everything is ok, start the persistent ramdisk sudo p3x-ramdisk start `) } module.exports.install = install; module.exports.load = load; module.exports.save = save; module.exports.start = start; module.exports.stop = stop; module.exports.watch = watch; module.exports.link = link; module.exports.status = status; module.exports.requireRoot = requireRoot; module.exports.defaults = defaults;templates/000077500000000000000000000000001516157350500130645ustar00rootroot00000000000000templates/p3x-ramdisk-timer.service.hbs000066400000000000000000000003751516157350500205060ustar00rootroot00000000000000[Unit] Description=P3X ramdisk persistent timer After=p3x-ramdisk.target [Service] Type=oneshot ExecStart={{ script }}/p3x-ramdisk.sh timer save TimeoutStopSec=infinity TimeoutStartSec=infinity TimeoutSec=infinity [Install] WantedBy=multi-user.target templates/p3x-ramdisk-timer.timer.hbs000066400000000000000000000002761516157350500201660ustar00rootroot00000000000000[Unit] Description=P3X ramdisk persistent timer After=p3x-ramdisk.target [Timer] OnCalendar=*:0/{{ timer }} OnBootSec=0min #OnUnitActiveSec={{ timer }}min [Install] WantedBy=timers.target templates/p3x-ramdisk.service.hbs000066400000000000000000000004501516157350500173620ustar00rootroot00000000000000[Unit] Description=P3X ramdisk persistent [Service] Type=oneshot RemainAfterExit=true ExecStartPre={{ script }}/p3x-ramdisk.sh boot load ExecStop={{ script }}/p3x-ramdisk.sh shutdown save TimeoutStopSec=infinity TimeoutStartSec=infinity TimeoutSec=infinity [Install] WantedBy=multi-user.target templates/p3x-ramdisk.sh000066400000000000000000000177351516157350500155770ustar00rootroot00000000000000#!/usr/bin/env bash DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ME="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")" P3X_UID={{ uid }} P3X_UID_NUMBER={{ uidNumber }} P3X_GID={{ gid }} P3X_GID_NUMBER={{ gidNumber }} ROOT={{ home }} PERSISTENCE=$ROOT/{{ persistent }} RAMDISK=$ROOT/{{ rampath }} TYPE=$1 COMMAND=$2 if [ -z "$COMMAND" ]; then COMMAND=$TYPE TYPE=terminal fi TRASH_NAME=.Trash-$P3X_UID_NUMBER PERSISTENCE_LOG=$PERSISTENCE/ramdisk-persistent.log #PERSISTENCE_LOG_LOAD=$PERSISTENCE/ramdisk-persistent-load.log #PERSISTENCE_LOG_SAVE=$PERSISTENCE/ramdisk-persistent-save.log PERSISTENCE_CURRENT=$PERSISTENCE/current PERSISTENCE_PREVIOUS=$PERSISTENCE/previous PERSISTENCE_LOCK=$PERSISTENCE/persistent.lock PERSISTENCE_TRASH=$PERSISTENCE/$TRASH_NAME RAMDISK_TRASH=$RAMDISK/$TRASH_NAME RAMDISK_PERSISTENCE=$RAMDISK/persistence RAMDISK_CONTENT=$RAMDISK_PERSISTENCE/content RAMDISK_CONTENT_LINK=$RAMDISK_CONTENT/.p3x-ramdisk-link RAMDISK_LOCK=$RAMDISK_PERSISTENCE/ramdisk.lock SUSPEND_ROOT=/lib/systemd/system-sleep SUSPEND_SCRIPT=$SUSPEND_ROOT/p3x-ramdisk.sh SYSTEMD=/etc/systemd/system function require_sudo() { if [[ $EUID -ne 0 ]]; then printf "You are not root!\n\n" exit 1 fi } function notify() { if hash notify-send 2>/dev/null; then notify-send P3X-RAMDISK $1 # else # date "$@" fi } function install() { require_sudo mkdir -p $PERSISTENCE_CURRENT mkdir -p $PERSISTENCE_PREVIOUS mkdir -p $PERSISTENCE_TRASH #mkdir -p $RAMDISK_CONTENT mkdir -p $RAMDISK_CONTENT_LINK printf "\n" >> $PERSISTENCE_LOG log "install" log "copy" cp $DIR/p3x-ramdisk-timer.service $SYSTEMD cp $DIR/p3x-ramdisk-timer.timer $SYSTEMD cp $DIR/p3x-ramdisk.service $SYSTEMD log suspend mkdir -p $SUSPEND_ROOT touch $SUSPEND_SCRIPT chmod u+x $SUSPEND_SCRIPT cat < $SUSPEND_SCRIPT #!/usr/bin/env bash ACTION=\$1 TYPE=\$2 LOG_DATA="\`date '+%Y-%m-%d %H:%M:%S'\`: SUSPEND \$TYPE \$ACTION" if [ "\$ACTION" == "pre" ]; then # Do the thing you want before suspend here, e.g.: sudo -u $P3X_UID printf "\n\$LOG_DATA Suspending" >> $PERSISTENCE_LOG $DIR/$ME suspend save elif [ "\$1" == "post" ]; then # Do the thing you want after resume here, e.g.: sudo -u $P3X_UID printf "\n\$LOG_DATA On again" >> $PERSISTENCE_LOG fi chown $P3X_UID_NUMBER:$P3X_GID_NUMBER $PERSISTENCE_LOG EOT log "reload services" systemctl daemon-reload log "install done" touch $PERSISTENCE_LOG # touch $PERSISTENCE_LOG_LOAD # touch $PERSISTENCE_LOG_SAVE fix_permissions } function start() { require_sudo install log "start" systemctl enable p3x-ramdisk systemctl enable p3x-ramdisk-timer.timer systemctl start p3x-ramdisk systemctl start p3x-ramdisk-timer.timer } function stop() { require_sudo printf "\n" >> $PERSISTENCE_LOG log "stop" systemctl stop p3x-ramdisk-timer.timer systemctl stop p3x-ramdisk systemctl disable p3x-ramdisk systemctl disable p3x-ramdisk-timer.timer if [ -d $SUSPEND_SCRIPT ]; then rm -rf $SUSPEND_SCRIPT fi if [ -f $SYSTEMD/p3x-ramdisk.service ]; then rm $SYSTEMD/p3x-ramdisk.service fi if [ -f $SYSTEMD/p3x-ramdisk-timer.timer ]; then rm $SYSTEMD/p3x-ramdisk-timer.timer fi if [ -f $SYSTEMD/p3x-ramdisk-timer.service ]; then rm $SYSTEMD/p3x-ramdisk-timer.service fi if [ -f $RAMDISK_LOCK ]; then rm $RAMDISK_LOCK fi } function fix_permissions() { chown $P3X_UID_NUMBER:$P3X_GID_NUMBER -R $RAMDISK chown $P3X_UID_NUMBER:$P3X_GID_NUMBER -R $PERSISTENCE # chown $P3X_UID_NUMBER:$P3X_GID_NUMBER $PERSISTENCE_LOG_LOAD # chown $P3X_UID_NUMBER:$P3X_GID_NUMBER $PERSISTENCE_LOG_SAVE } function log() { if [ -z ${2+x} ]; then false; else notify $1 fi LOG_DATA="`date '+%Y-%m-%d %H:%M:%S'`: $TYPE $1" echo $LOG_DATA echo $LOG_DATA >> $PERSISTENCE_LOG } function timer_start() { SECONDS=0 STARTED=`date '+%Y-%m-%d %H:%M:%S'` } function timer_end() { DURATION=$SECONDS PERSISTENCE_UPDATED_AT=$PERSISTENCE/$1 echo $STARTED > $PERSISTENCE_UPDATED_AT echo `date '+%Y-%m-%d %H:%M:%S'` >> $PERSISTENCE_UPDATED_AT DURATION_STRING="$(($DURATION / 60)) minutes $(($DURATION % 60)) seconds" echo $DURATION_STRING >> $PERSISTENCE_UPDATED_AT chown $P3X_UID_NUMBER:$P3X_GID_NUMBER $PERSISTENCE_UPDATED_AT log "$DURATION_STRING" } function load() { timer_start printf "\n" >> $PERSISTENCE_LOG log "loading" if [ -f $PERSISTENCE_LOCK ]; then log "has a lock at $PERSISTENCE_LOCK ! not loading! quitting..." true return fi if [ -f $RAMDISK_LOCK ]; then log "already loaded! quitting, existing ramdisk lock: $RAMDISK_LOCK" true return fi cd $PERSISTENCE_CURRENT #tar xvf $PERSISTENCE_COMPRESSED_CURRENT >$PERSISTENCE_LOG_LOAD log "load $PERSISTENCE_CURRENT to $RAMDISK_CONTENT" mkdir -p $RAMDISK_CONTENT cp -avr . $RAMDISK_CONTENT > /dev/null #$PERSISTENCE_LOG_LOAD #rsync -atvq --delete . $RAMDISK_CONTENT > /dev/null #$PERSISTENCE_LOG_LOAD log "loaded" true if ! [ -d $RAMDISK_TRASH ]; then ln -s $PERSISTENCE_TRASH $RAMDISK fi # truncate $PERSISTENCE_LOG_LOAD # chown $P3X_UID_NUMBER:$P3X_GID_NUMBER $PERSISTENCE_LOG_LOAD fix_permissions timer_end "update-at-load.log" echo `date '+%Y-%m-%d %H:%M:%S'` > $RAMDISK_LOCK } function truncate() { tail -n 10240 $1 > $1.1 mv $1.1 $1 } function internal_save() { FROM=$1 TO=$2 log "save $FROM to $TO" cd $FROM rsync --rsync-path="nice -n19 ionice -c3 rsync" -aq --delete . $TO > /dev/null #$PERSISTENCE_LOG_SAVE log "saved" # truncate $PERSISTENCE_LOG_SAVE } function save() { printf "\n" >> $PERSISTENCE_LOG timer_start log "save" if [ -f $RAMDISK_LOCK ]; then if [ -f $PERSISTENCE_LOCK ]; then log "has a lock at $PERSISTENCE_LOCK ! quitting..." true return fi touch $PERSISTENCE_LOCK log "save, current to previous" internal_save $PERSISTENCE_CURRENT $PERSISTENCE_PREVIOUS log "save, ramdisk to current" internal_save $RAMDISK_CONTENT $PERSISTENCE_CURRENT rm $PERSISTENCE_LOCK log "save done" true # cannot use it at save, it will change modification #fix_permissions truncate $PERSISTENCE_LOG timer_end "update-at-save.log" else log "not saving, not loaded" true fi } function link() { log "link" if [ -d "$RAMDISK_CONTENT_LINK" ]; then cd $RAMDISK_CONTENT_LINK shopt -s dotglob for d in */ ; do if [ "$d" = "*/" ]; then continue fi GENERATED_LINK="${ROOT}/${d}" DIR=${d%/*} log "link $RAMDISK_CONTENT_LINK/$DIR to $ROOT/$DIR" # delete actual directory, no slash! otherwise it shows not empty if [ -d "${ROOT}/${DIR}" ]; then unlink "${ROOT}/${DIR}" || true fi ln -s "${RAMDISK_CONTENT_LINK}/${DIR}" $ROOT done fi log "link done" } if [ "$COMMAND" == "load" ] then load exit fi if [ "$COMMAND" == "save" ] then save exit fi if [ "$COMMAND" == "link" ] then link exit fi if [ "$COMMAND" == "start" ] then start exit fi if [ "$COMMAND" == "stop" ] then stop exit fi if [ "$COMMAND" == "install" ] then install exit fi if [ "$COMMAND" == "watch" ] then WATCH1="df -h | grep -e " WATCH2=$RAMDISK WATCH3=" -e Size" watch $WATCH1$WATCH2$WATCH3 exit fi cat <&1 Eg: sudo $ME install sudo $ME start $ME watch $ME save $ME load Unknown type: {$TYPE} command: {$COMMAND} Requires 2 parameters: type: anything (like boot, timer, terminal), default is "terminal" command: install, start, stop, load, save, watch EOT