hexparrot / mineos-node

node.js implementation of mineos minecraft management
GNU General Public License v3.0
334 stars 170 forks source link

[FreeBSD] Issue reading correct /proc location #232

Closed GiantTreeLP closed 7 years ago

GiantTreeLP commented 7 years ago

On FreeBSD there is no /proc/uptime so mineos thinks it is running in a compatibility layer.
But in there is no /usr/compat/linux/proc/uptime either.

So PROC_PATH is left being null and no profile can be created.

Error:

{"date":"Sun Feb 19 2017 02:16:02 GMT+0100 (CET)","process":{"pid":82781,"uid":0,"gid":0,"cwd":"/usr/local/games/minecraft","execPath":"/usr/local/bin/node","version":"v7.5.0","argv":["/usr/local/bin/node","/usr/local/games/minecraft/webui.js"],"memoryUsage":{"rss":104742912,"heapTotal":74108928,"heapUsed":36098312,"external":920967}},"os":{"loadavg":[1.51806640625,1.69189453125,1.77685546875],"uptime":1063285},"trace":[{"column":18,"file":"fs.js","function":"Object.fs.readdirSync","line":871,"method":"fs.readdirSync","native":false},{"column":17,"file":"/usr/local/games/minecraft/mineos.js","function":"Object.mineos.server_pids_up","line":54,"method":"mineos.server_pids_up","native":false},{"column":27,"file":"/usr/local/games/minecraft/mineos.js","function":"mineos.mc.self.property","line":1245,"method":"mc.self.property","native":false},{"column":10,"file":"/usr/local/games/minecraft/mineos.js","function":"self.verify","line":1503,"method":"verify","native":false},{"column":23,"file":"/usr/local/games/minecraft/node_modules/async/lib/async.js","function":null,"line":760,"method":null,"native":false},{"column":37,"file":"/usr/local/games/minecraft/node_modules/async/lib/async.js","function":null,"line":166,"method":null,"native":false},{"column":13,"file":"/usr/local/games/minecraft/node_modules/async/lib/async.js","function":null,"line":718,"method":null,"native":false},{"column":13,"file":"/usr/local/games/minecraft/node_modules/async/lib/async.js","function":"iterate","line":262,"method":null,"native":false},{"column":29,"file":"/usr/local/games/minecraft/node_modules/async/lib/async.js","function":null,"line":274,"method":null,"native":false},{"column":16,"file":"/usr/local/games/minecraft/node_modules/async/lib/async.js","function":null,"line":44,"method":null,"native":false}],"stack":["TypeError: path must be a string or Buffer","    at Object.fs.readdirSync (fs.js:871:18)","    at Object.mineos.server_pids_up (/usr/local/games/minecraft/mineos.js:54:17)","    at mineos.mc.self.property (/usr/local/games/minecraft/mineos.js:1245:27)","    at self.verify (/usr/local/games/minecraft/mineos.js:1503:10)","    at /usr/local/games/minecraft/node_modules/async/lib/async.js:760:23","    at /usr/local/games/minecraft/node_modules/async/lib/async.js:166:37","    at /usr/local/games/minecraft/node_modules/async/lib/async.js:718:13","    at iterate (/usr/local/games/minecraft/node_modules/async/lib/async.js:262:13)","    at /usr/local/games/minecraft/node_modules/async/lib/async.js:274:29","    at /usr/local/games/minecraft/node_modules/async/lib/async.js:44:16"],"level":"error","message":"uncaughtException: path must be a string or Buffer","timestamp":"2017-02-19T01:16:02.073Z"}

File in question: https://github.com/hexparrot/mineos-node/blob/master/mineos.js

I have fixed this by commenting out line 35

fs.statSync('/proc/uptime');

So that PROC_PATH = '/proc'; runs successfully. The rest works fine after that, but it doesn't seem to be a real fix.

EDIT: I should note that I run mineOS in a FreeBSD jail.

hexparrot commented 7 years ago

Is it a possible fix for you to have your FreeBSD jail mount the Linux Compatibility Proc Filesystem and then use the script as written?

This is the preferable way to make sure you get all the information the webui intends to display on the dashboard, but if MineOS has no availability to get uptime, then either a) add uptime or b) would you want this removed from the dash?

GiantTreeLP commented 7 years ago

Well, the uptime works, it's just not a file in `/proc.

The compatibility file system also doesn't offer uptime for me.

This is because it gets the uptime of the host and not the jail (a jail does not have a uptime).

hexparrot commented 7 years ago

Ok, I understand the issue. As is, MineOS uses a python call os.uptime for the actual information, but is simply using uptime as a verification of the location /proc filesystem, which we can see is a false negative (for getting the uptime).

The PROC_PATH is actually used for something completely different; in this case, it's used for identifying which FS path will provide the base path for all the PIDs for open processes.

Can you verify that (with your fix) you still can see the memory usage of all the servers? If you can't we'd need to determine which is the best place for MineOS to get this information using the npm module procfs-stats

GiantTreeLP commented 7 years ago

So, even though the process ID is present in /proc, MineOS is unable to get the memory usage for any server.

It can get the memory statistics for the whole host, though.

hexparrot commented 7 years ago

Well, it's to be expected. Basically, even if the directory structure design is the same between Linux and FreeBSD, the actual structure of the files themselves do not match, hence the dysfunction.

According to this post, it is possible to mount the Linux-compatible Proc FS through the use of jail_jailname_mount_enable="YES"; see the below post for more instruction.

https://forums.freebsd.org/threads/6019/

Unless procfs-stats decides to become FreeBSD-compatible (which I don't foresee anytime soon), the only way to fix this otherwise would be for me to ...well, effectively code a new procfs-stats or fork/fix it myself, which I'm unlikely to be able to pull off. I think this jail-mounting procfs is the best bet.

wasurerarenai commented 7 years ago

I can confirm removing/reordering the /proc entry in mineos.js fixes this issue on FreeBSD 11 Jail environments. Even with linprocfs mounted per your wiki/install instructions the missing "uptime" entry breaks the check. If the script checked for uptime's existence in the directory first may help with skipping unusable detected directories.

var proc_paths = [
  '/usr/compat/linux/proc',
  '/proc',
  '/system/lxproc'
]

linprocfs is loaded/mounted within the jail

[user@host/mnt/pool]$ kldstat | grep linprocfs
31    1 0xffffffff82cc6000 a87b     linprocfs.ko

[user@host /mnt/pool]$ mount | grep linprocfs
linprocfs on /mnt/pool/jails/mineos/usr/compat/linux/proc (linprocfs, local)

/proc is missing "uptime" where-as the compat fs has it.

[user@host /mnt/pool]$ sudo jexec mineos tcsh
root@mineos:/ # ls -l /proc /usr/compat/linux/proc/
/proc:
total 0
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 13124
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 13161
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 13193
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 85253
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 86321
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 86401
lr--r--r--  1 root  wheel  0 Aug 28 16:38 curproc -> 86401

/usr/compat/linux/proc/:
total 0
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 13124
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 13161
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 13193
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 85253
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 86321
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 86401
-r--r--r--  1 root  wheel  0 Aug 28 16:38 cmdline
-r--r--r--  1 root  wheel  0 Aug 28 16:38 cpuinfo
-r--r--r--  1 root  wheel  0 Aug 28 16:38 devices
-r--r--r--  1 root  wheel  0 Aug 28 16:38 filesystems
-r--r--r--  1 root  wheel  0 Aug 28 16:38 loadavg
-r--r--r--  1 root  wheel  0 Aug 28 16:38 meminfo
-r--r--r--  1 root  wheel  0 Aug 28 16:38 mounts
-r--r--r--  1 root  wheel  0 Aug 28 16:38 mtab
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 net
-r--r--r--  1 root  wheel  0 Aug 28 16:38 partitions
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 scsi
lr--r--r--  1 root  wheel  0 Aug 28 16:38 self -> 86401
-r--r--r--  1 root  wheel  0 Aug 28 16:38 stat
-r--r--r--  1 root  wheel  0 Aug 28 16:38 swaps
dr-xr-xr-x  1 root  wheel  0 Aug 28 16:38 sys
-r--r--r--  1 root  wheel  0 Aug 28 16:38 uptime
-r--r--r--  1 root  wheel  0 Aug 28 16:38 version
hexparrot commented 7 years ago

I'm not entirely sure why this could have fixed it, re-ordering the paths.

for (var proc in proc_paths) {
  try {
    fs.statSync(path.join(proc_paths[proc], 'uptime'));
    PROC_PATH = proc_paths[proc];
    break;
  } catch (e) {}
}

Per this code, if the first check /usr/compat/linux/proc/uptime--it is tested via the statSync. If that fails (and it should, with uptime absent), it should error out, run the empty catch block then hit up the next path iteration. Only until it finds uptime should PROC_PATH get permanently set.

In other words, I have no idea why /proc/uptime in your jail would not error out and skip to the next for loop.

Regardless, reordering it doesn't cause any regression issues, so I made this change and pushed it just now: aa815ba3228e9c8f2efdcd04bfd72104732b0ba5

Let me know if this solves the issue straight from the HEAD.