I am using tcl.lang.Interp.eval() to execute a "hello world" tcl script. The command used to execute the script is something like this-
source /path/of/my/script.tcl
Now how do I execute the script as sudo user as we cannot execute source using sudo through java program?
You can run tclsh (the “mothership” implementation of Tcl, written in C) from inside sudo just fine, or you can run a JVM which uses the TclJava library. However, sudo runs whole processes with elevated privileges and not just a library; you need to think in terms of creating a program that will do what you want, possibly with suitable arguments passed in.
FWIW, I'd start by trying:
sudo tclsh /path/of/my/script.tcl
That's going to be the simplest if it works; it's how tclsh is designed to be used (plus sudo). It's only unsuitable if the script requires access to an in-process JVM. If that's the case, you're probably going to have to write a small wrapper Java program.
Related
I'm writing a Java program that calls other programs, and some of them need to be ran as root.
I thought about running the whole JAR as root but that sounds like a security risk, I'd rather run just some programs as root.
Currently, I create a ProcessBuilder and use its getStandardOutput method to instantiate a Writer, on the command sudo -S pacman <...>. (-S means ‘read from standard input’).
I then inject the password using that reader and flush it, so far so good.
However, when pacman expects input (for example when asking an interactive yes/no question), and I try to write to the Writer again, it fails with IOException because the stream is closed.
How can I get a Writer that can actually send characters to pacman and other programs ran as root?
This program is only expected to run on UNIX (Arch Linux, Debian, MacOS and maybe Window's WSL) so UNIX-specific solutions are fine, if possible I'd rather not use JNI because it requires to compile multiple times, but if that's the only solution it's fine. I'm also fine replacing sudo with something else as long as it's still ran as root.
If this is not a long-lived service, you could run sudo -v to have sudo cache the credentials and then invoke sudo in your Java program without needing to enter a password. This would work best if you invoked your Java program with something like:
#!/bin/bash
sudo -v
java -jar ...
I researched this question and all answers suggest visudo to add:
Defaults:user !requiretty
It does not work!
I have two Linux boxes (RedHat). I have a Java class which uses ProcessBuilder/Process to execute commands. The class runs under a system account.
On both boxes, I run
su other-user -c 'some-command'
and provide the password for other-user in an input stream to the Process object.
On one box, the command succeeds and on the other I get the error above.
The sudoers files on both machines did not have exclusions for requiretty ('Defaults requiretty' is set on both files).
I tried adding the exclusion as suggested by the answers I found. I tried both the system user running the process and 'other-user'...
Does not work.
What else can be the issue? Do I need to restart the system after adding the requiretty exceptoin(s)?
sudoers is for sudo rather than su so you should use sudo.
According to su manual:
-c, --command COMMAND
Specify a command that will be invoked by the shell using its -c.
The executed command will have no controlling terminal. This option cannot be used to execute interactive programs which need a controlling TTY.
you can use a TTY spawning if you are trying to avoid using sudo or you don't have a sudo privileges.
Just invoke one of the following codes before running the code which giving you the error you mentioned.
here are some examples of codes you can use, depends on the code or the system you are using:
python -c 'import pty; pty.spawn("/bin/sh")'
echo os.system('/bin/bash')
/bin/sh -i
perl —e 'exec "/bin/sh";'
perl: exec "/bin/sh";
ruby: exec "/bin/sh"
lua: os.execute('/bin/sh')
(From within IRB)
exec "/bin/sh"
(From within vi)
:!bash
(From within vi)
:set shell=/bin/bash:shell
(From within nmap)
!sh
the first three choices up are my common used ones, and I am trusting their results.
I am using them while pentesting.
I'm working on a cross-platform installation utility written in Java. I would like to be able to execute shell commands, for example "apt-get ..." on Linux. I'm using the ProcessBuilder API for this purpose.
Unfortunately, some commands require root privileges. I would like to execute the following shell command as root:
bash -c apt-get install -y [some package]
If I try to add "sudo" before "apt-get" nothing works because there is no terminal "sudo" can get the password from.
What should I do in order to ask the user for a password and then execute the above mentioned shell command?
A short code snippet would be very appreciated!
Thanks in advance!
Max
You could run gksudo <your command> but this ties your application to a certain UI, e.g. gnome, kde, etc.
You could write all the the root-tasks to a scriptfile and ask the user to execute it with root privileges. I know this sounds clumsy, but its done that way by quite a lot of "enterprise level" software vendors (e.g. the (Java-) installer of the Oracle RDBMS at least up to 11g).
The following doesn't work in Java (an exception is thrown):
Runtime.getRuntime().exec("cd mydir; myprog");
The same works fine in PHP:
exec("cd mydir; myprog");
What exactly is different in Java's implementation and why (it seems more limited at first glance)?
the java exec command does not use the system command interpreter. something like "cd mydir; myprog" depends on the system command line interpreter (e.g. on windows cmd, on linux sh) to split that into 2 separate commands and execute each of them. java does not invoke the system command interpreter, so that does not work. you either need to call each command separately, or invoke the desired interpreter yourself as part of the command line.
I've seen people have problems like this, and I'm sure there are several ways, however the one I've seen most people reply is this. add cmd before it.
Runtime.getRuntime().exec("cmd cd mydir; myprog");
Assuming you're running an applet, not Java in a CLI environment on the server? If so, then your Java runtime is running on the client computer, not the server.
Java also has a better way to handle multiple commands than your semicolon. Instead of using the signature:
Runtime.exec(String)
try using this for each of your commands:
Runtime.exec(String[])
and make each argument of your command an element in the String array.
I am running a shell script through a web application. This shell script looks something like
`#! /bin/bash
user=""
pass=""
db_url=""
db_instance=""
sqlplus -s $user/$pass#$db_url/$db_instance # ./SqlScripts/foo.sql
sqlplus -s $user/$pass#$db_url/$db_instance # ./SqlScripts/bar.sql
CLASS_PATH="./lib/*"
java -classpath $CLASS_PATH package.Main ./Data/inputfile`
I am using ProcessBuilder to run the script and everything but the last line works fine. Am I creating a problem by calling shell through the jvm then calling the jvm again to run the application?
The problem was the environment that the script execution process was running in. I changed some of the environment variables of the process and everything is working fine now. The script was initially a standalone shell script, but I wrote one script for each of the databases used. In order to control the workflow I wrote a web application for this which calls seperate threads for each script and can manage the threads. Thanks for the responses!
Often, app servers run their servlets in a 'clean room' environment - e.g. they strip away all the variables that would normally be set from the outside for security reasons. Try using a fully qualified path to the java binary, and also try setting a full/absolute path for your CLASS_PATH variable.
The parent JVM and the child JVM should be separate processes, no particular reason why they should interfere.
What error do you get?
is java on your PATH?
OK, adding more questions in response to your comments ...
Which thread is waiting? Presumably the parent?
The child java process, do you have any evidence as to whether is succesfully initalises. My guess woukld be that the child is in some way blocked. If you kill the child does the parent then come back to life?
Suppose it was a simple "hello world" application, would that work?
Most likely the line:
CLASS_PATH="./lib/*"
And
$CLASS_PATH
It won't be expanded by the process builder because that's usually shells' job, which in this situation is not being invoked.
Try creating the complete list of ./lib/* and append it directly into the last line of your script.
java -classpath ./lib/a.jar:./lib/b.jar
Side note:
Invoking all this from java looks just bad to me. I would rather have it in a standalone script and invoke it by other means, but that's me.