I want to start the following file called test.sh as a specific user from superuser Ruby.
#!/bin/bash
echo "test.sh ok"
id
gid = 1001
uid = 1001
pid = fork do
  exit 127 unless Process::GID.change_privilege(gid) == gid
  exit 127 unless Process::UID.change_privilege(uid) == uid
  begin
    exec './test.sh'
  rescue  # Errno::ENOENT
    exit 127
  end
  exit 127  #Something else
end
res = Process.waitpid(pid)
puts 'complete'
p $?
Execution result
$ sudo ruby a.rb 
test.sh ok
uid=1001(****) gid=1001(****) groups=1001(****),0(root)
complete
#<Process::Status: pid 75202 exit 0>
--spawn does not have a function to change the user, so fork and then ʻexec.  ――This is easy if everything is successful. I want to think about error handling in the case of failure.  --Variables should not be shared because it is fork and is a separate process. ʻIO.pipe is also stupid
--ʻAbortThen, it is indistinguishable from the case where the application failed when exec succeeded.  --Therefore, the exit code127 (that is, ʻENOENT) tells the failure. I can't tell if the application returns 127 when the exec is successful, but I'll leave it out.