Starting PM2 as a non-root user is broken #1321

Closed
akloeber opened this Issue May 29, 2015 · 27 comments

Projects

None yet
@akloeber

In latest v0.12.15 starting PM2 as a non-root user via the generated startup script does not work anymore.
Steps to reproduce:

root# pm2 startup ubuntu -u someUser
root# /etc/init.d/pm2-init.sh start
Starting pm2

fs.js:647
  return binding.mkdir(pathModule._makeLong(path),
                 ^
Error: EACCES, permission denied '/root/.pm2'
    at Object.fs.mkdirSync (fs.js:647:18)
    at Object.CLI.pm2Init (/usr/local/lib/node_modules/pm2/lib/CLI.js:37:8)
    at Object.<anonymous> (/usr/local/lib/node_modules/pm2/bin/pm2:20:5)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:902:3

Folder '/root/.pm2' got created by pm2 startup and is owned by root. The existence of this folder is strange by itself because PM2 should be run as someUser and not as root (already described in #933) but at least it worked in v0.12.11.

Environment:
PM2 v0.12.15
node v0.10.25
Ubuntu 14.04.2 LTS

@akloeber

After some analysis I found the change that breaks the startup script.
Variable PM2_HOME (which has the fix value of /root/.pm2 in the script) is now passed when executing PM2 (that was added recently and does not make much sense when PM2 should not be run as root):

su - $USER -s $shell -c "PATH=$PATH; PM2_HOME=$PM2_HOME $*"

If passing of PM2_HOME is removed (su - $USER -s $shell -c "PATH=$PATH; $*") everything works with v0.12.15.

@dceejay dceejay added a commit to node-red/node-red.github.io that referenced this issue Jun 4, 2015
@dceejay dceejay Add temp note to PM2 docs (re init script error issue) d32d9b4
@akloeber

I solved it for myself by providing a fixed init script like this:

#...

NAME=pm2
PM2=/usr/local/lib/node_modules/pm2/bin/pm2
USER=someUser

export PATH=/usr/bin:$PATH

get_user_info() {
    echo $(getent passwd ${1:-`whoami`})
}

get_user_shell() {
    local shell=$(get_user_info $1 | cut -d: -f7)

    if [[ $shell == *"/sbin/nologin" ]] || [[ $shell == "/bin/false" ]] || [[ -z "$shell" ]];
    then
      shell="/bin/bash"
    fi

    echo $shell
}

get_user_home() {
    local home=$(get_user_info $1 | cut -d: -f6)

    echo $home
}

super() {
    local shell=$(get_user_shell $USER)
    local home=$(get_user_home $USER)/.pm2
    su - $USER -s $shell -c "PATH=$PATH; PM2_HOME=$home $*"
}

#...

Note: Whitespace is removed automatically in get_user_info by echoing without wrapping expression in quotes, so invoking sedis no more necessary.

@tomyam1
tomyam1 commented Aug 28, 2015

Just encountered this issue myself.

The user running pm2 is not a sudoer so when I ran pm2 startup ubuntu, I got this message:

tepez-server@api-server:~$ pm2 startup ubuntu
[PM2] You have to run this command as root. Execute the following command:
      sudo su -c "env PATH=$PATH:/home/tepez-server/.nvm/versions/node/v0.12.7/bin pm2 startup ubuntu -u tepez-server"

When I ran the command suggested by pm2 PM2_HOM in the generated script was invalid:

export PM2_HOME="/root/.pm2"

A simple solution was to add an export for PM2_HOME to the script

sudo su -c "export PM2_HOME=/home/tepez-server/.pm2 && env PATH=$PATH:/home/tepez-server/.nvm/versions/node/XXX/bin pm2 startup ubuntu -u tepez-server"

I think this is the script pm2 should instruct to run.

@Telemakhos

To fix Error: EACCES, permission denied '/root/.pm2', in /etc/init.d/pm2-init.sh change the line

export PM2_HOME="/root/.pm2"

to

export PM2_HOME="/home/<your_user>/.pm2"
@joeroback

I added to the init script

get_user_home() {
    local home=$(getent passwd ${1:-`whoami`} | cut -d: -f6 | sed -e 's/[[:space:]]*$//')

    if [[ -z "$home" ]];
    then
        home="/root"
    fi

    echo "$home"
}

then in super()

super() {
    local shell=$(get_user_shell $USER)
    local home=$(get_user_home $USER)
    su - $USER -s $shell -c "PATH=$PATH; PM2_HOME=$home/.pm2 $*"
}
@cuteboi
cuteboi commented Oct 5, 2015

So, is this going upstream at some point? I was surprised something reported in 2014 (in other reports) still remains in late 2015

@cuteboi
cuteboi commented Oct 5, 2015

So, is this going upstream at some point? I was surprised something reported in 2014 (in other reports) still remains in late 2015

@Unitech
Owner
Unitech commented Oct 6, 2015

waiting for PR

@charles-cai

Where's the equivalent /etc/init.d/pm2-init.sh in systemd (on Yocto/Intel Edison board environment)?

@rudders
rudders commented Nov 26, 2015

+1

@Pierre-Gilles

+1

@marcortw

+1

@40thoughts

+1

@neolectron

+1

@ronenteva

+1

@Unitech
Owner
Unitech commented Mar 2, 2016

Closing in favor of #1035

@Unitech Unitech closed this Mar 2, 2016
@RafaPolit

This is still happening on May 2016 and the issue this was 'closed in favor of', has absolutely nothing to do with this issue!

For me, @Telemakhos solution worked.

Thanks,
Rafa.

@Boycce
Boycce commented May 10, 2016

@RafaPolit @Unitech I am confused also?

@ronenteva

I'm still having this issue, and I'm not sure how related it is to #1035.
On May 10, 2016 7:43 AM, "Ricky Boyce" notifications@github.com wrote:

@RafaPolit https://github.com/RafaPolit @Unitech
https://github.com/Unitech I am confused also?


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#1321 (comment)

@Florentijn

+1

@josephrocca

I'm getting this error for pm2 commands if I don't use sudo:

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: connect EACCES /home/username/.pm2/rpc.sock
    at Object.exports._errnoException (util.js:1022:11)
    at exports._exceptionWithHostPort (util.js:1045:20)
    at PipeConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
@vmarchaud
Collaborator

Because the user who launched the daemon isn't the same as the one who trying to connect, you need to review the chmod of the dir to be able to share the daemon.

@josephrocca
josephrocca commented Jan 14, 2017 edited

@vmarchaud I've tried full re-installs many times now (npm uninstall + delete persistent pm2 files including ~/.pm2) and the same thing always happens. Any reason why pub.sock and rpc.sock become owned by root? Seems that it only happens after reboot (after fresh install).

-rw-rw-r-- 1 username  username  4329 Jan 14 16:57 dump.pm2
drwxrwxr-x 2 username  username  4096 Jan 14 16:56 logs
-rw-rw-r-- 1 username  username     2 Jan 14 16:55 module_conf.json
drwxrwxr-x 2 username  username  4096 Jan 14 16:57 pids
-rw-rw-r-- 1 username  username  3043 Jan 14 16:57 pm2.log
-rw-rw-r-- 1 username  username     4 Jan 14 16:57 pm2.pid
srwxr-xr-x 1 root root    0 Jan 14 16:57 pub.sock
srwxr-xr-x 1 root root    0 Jan 14 16:57 rpc.sock
-rw-rw-r-- 1 username  username    13 Jan 14 16:55 touch

My general pattern has been:

  • full reinstall (with sudo)
  • add app.js
  • pm2 startup
  • reboot (and now I get error if I don't use sudo - before this step I didn't have to)

In any case, I don't mind using sudo but it's just a bit strange/annoying :/

@vmarchaud
Collaborator

Because the daemon as been started by root user, you need to install and run pm2 as your user.

@josephrocca
josephrocca commented Jan 15, 2017 edited

you need to install and run pm2 as your user

I have been. I don't use root (except via sudo, which is needed for installation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment