Shell script works when run in terminal but not when run through OS.execute()

Godot Version

4.4.1

Question

Arch Linux, KDE, X11

I want to detect whether my cursor is currently grabbed (system-wide, so the Input singleton will not work for this). I have a shell script called test.sh in the project’s root directory.

#!/bin/bash
cat /var/log/Xorg.0.log

This is the function where I try to run the script.

func _on_timer_check_pointer_timeout() -> void:
	var output_grabs: Array[String] = []
	
	var output_dict: Dictionary[String, float] = {}
	
	var exit_code_grabs = OS.execute("./test.sh", [], output_grabs, true)
	
	var output_grabs0 := output_grabs[0].split("\n")
	print(output_grabs0)

When I right-click on test.sh in my file browser and select “Run In Konsole” it prints the contents of the file as expected. The output of the godot function, however, is:

["cat: /var/log/Xorg.0.log: No such file or directory", ""]

“ls -s” gives me this for test.sh:

-rwxr-xr-x  1 pgcomai pgcomai    36 Feb  5 14:38 test.sh

I am using a shell script because I figured it might work better than putting it all in the arguments of OS.execute(), which did not work. The following code, which I use to poll hardware temps, works just fine.

var exit_code_name = OS.execute("bash", ["-c", "cat /sys/class/hwmon/hwmon*/name"], output_name)
var exit_code_temp = OS.execute("bash", ["-c", "cat /sys/class/hwmon/hwmon*/temp1_input"], output_temp)

Any insight would be helpful. I don’t know if the problem is Linux, Godot, the fact that I’m trying to read in /var instead of /sys, or all of those together.

P.S. As a sanity check, I can confirm that the following also does not work and gives the same “no such file or directory” output.

OS.execute("bash", ["-c", "cat /var/log/Xorg.0.log"], output_grabs, true)

I believe the script test.sh is indeed found, but the file /var/log/Xorg.0.log isn’t, so lsing to find test.sh wouldn’t help ! Maybe that said log file just does not exist at all during Godot runtime? Try executing ls /var/log via bash within a script right before executing cat

PS: I’m familiar with linux and its filesystem, alongside bash and its usage, however I’m no specialist when it comes to Xorg logs or whatever this is

The result of running this script

#!/bin/bash
ls /var/log

is the following output:

["ls: cannot access \'/var/log\': No such file or directory", ""]

Maybe Godot just can’t see anything within /var?

You can test this inside of Godot.

if Input.mouse_mode == Input.MouseMode.MOUSE_MODE_CAPTURED:
	print("captured")

As for your issues in the OS, my understanding is that you can only operate in your program root or where ever user data is stored. AFAIK, Godot does not actually allow you to access the root of the OS. This would be supported by the fact that the files has read permissions and you still cannot access it.

Unfortunately checking Input.mouse_mode only tells me if this Godot instance is grabbing my cursor. I want to check system-wide if any application is grabbing.

As for not being able to access the root directory, I am still able to access /sys, which is right beside /var in the root directory. It is possible that I am not able to access /var specifically from Godot though.

What’s ls -ld /var give you? I suspect that while the file may be permissive, /var may not be.

Another potential approach, since you’re just using cat to read the file is you just use DirAccess in Godot to open the file and parse it inside Godot.

ls -ld /var returns this:

drwxr-xr-x 13 root root 4096 Feb  5 14:36 /var

DirAccess says no files exist at /var/log and FileAccess cannot open the log file in question.

var d := DirAccess.open("/var/log")
print(DirAccess.get_open_error())

The above returns error 31. The documentation says it is ERR_INVALID_PARAMETER.

Unfortunately, I am out of ideas. It’s been years since I’ve used Linux, and I’ve never run Godot on Linux. Hopefully someone who has will have some more ideas.

1 Like

I can’t run your exact example as I’m on Fedora (I do run XOrg, but logs are per session/user and filed away under our home dir).

But changing test.sh to cat /var/log/dnf.log instead and then sticking your GDScript in a random project works just fine.

So I presume this is not a Godot issue.

Your system may be better locked down than mine though, have you checked logs for any SELinux shenanigans?

1 Like

As far as I can tell, I am not running SELinux. The logs sometimes mention it in a list of packages, but it is prefaced with a - instead of a +. I do suspect that the system is locking down /var/log, though. Running “ls /var” from Godot excludes some directories including log:

["cache", "config", "data", "db", "run", "tmp", ""]

I tried checking permissions with acl:

[pgcomai@archlinux ~]$ getfacl /var/log
getfacl: Removing leading '/' from absolute path names
# file: var/log
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

[pgcomai@archlinux ~]$ getfacl /var/spool
getfacl: Removing leading '/' from absolute path names
# file: var/spool
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

[pgcomai@archlinux ~]$ getfacl /sys/class/hwmon/hwmon0
getfacl: Removing leading '/' from absolute path names
# file: sys/class/hwmon/hwmon0
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

My hunch is that I will have to make some other app or script that reads the log as root and then writes that somewhere else for Godot to read.

Can you run xprop ?

xprop -root _NET_ACTIVE_WINDOW will give you the ID of the active window, you can deduce whether or not it’s your Godot app from there

-root here means root window, not root privileges

xprop - property displayer for X

I can run xprop but I cannot find a property that changes depending on whether a window is grabbing my cursor. If I run xprop -spy I see no changes when a window grabs or releases the cursor.