Solved Environmental variable in a jail

lib13

Member

Reaction score: 3
Messages: 97

I'd like to set an environmental variable that could be set when the jail starts.

In the command line (csh), if i do:

Code:
>setenv KK "whatevercsh"
>printenv  | grep KK
KK=whatevercsh
In the command line (bash), it also works although with:
Code:
# KK="whateverbash"; export KK                                                                                                                                                                                                        
# printenv | grep KK
KK=whateverbash
Fine.
But what about having it when the jail is started?
Tried to place KK="whateversh"; export KK in /etc/rc.local as it seems that /etc/rc.local is interpreted by /bin/sh, but KK was never set.
Also tried to call a script from /etc/rc.local, either in the csh or the bash versions of it, but the variable remained not set.

From the man page of rc.local(8), it's said:
if you want to use rc.local, it is still supported. In this case, it should source /etc/rc.conf and contain additional custom startup code for your system.
Tried to do this. cat /etc/rc.local:
Code:
. /etc/rc.conf
KK="whatever"; export KK
But to no success.

So, my question. How to set a variable at the boot of a jail?
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

I'd like to set GOPATH for a Go system.
I test it like printenv | grep KK.
Or when under a bash prompt, set | grep KK.
 

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 7,695
Messages: 30,639

I test it like printenv | grep KK.
Or when under a bash prompt, set | grep KK.
Where and how are you executing this in the jail? The way you access the shell can be done through different ways. Shells typically use different files when started interactive vs. non-interactive and login vs. non-login. For sh(1) for example, the /etc/profile is only loaded when it's a login shell. Bash is even worse when it comes to startup scripts.
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

Where and how are you executing this in the jail? The way you access the shell can be done through different ways. Shells typically use different files when started interactive vs. non-interactive and login vs. non-login. For sh(1) for example, the /etc/profile is only loaded when it's a login shell. Bash is even worse when it comes to startup scripts.
Yes, I know. That's why I didn't do it before. But since Wozzeck.Live mentioned it, I also tested it.
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

An environment is set for a specific proces. A jail is simply a collection of processes chrooted in a specific base directory.
So you have to tell us in which process you need the environment variable set?

For example if you open a console in the jail (csh, bash or whatever shell) and you want to have it in your shell environment, then you simply use /.bashrc or /.profile just like outside the jail. Put the environment variable in $jailRoot/home/YourUser/.bashrc or .cshrc.

If you run a specific script or service in the jail (a Go program, for example), then you need to put the environment variable in the environment of that process. This depends on how do you start the process.
For example, if you run a Go program by calling a starter script in the jail with exec.poststart, then you could put the environment variable in the starter script.
It depends on your concrete solution for starting the jail and in which process do you need the variable.
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

If you run a specific script or service in the jail (a Go program, for example), then you need to put the environment variable in the environment of that process. This depends on how do you start the process.
For example, if you run a Go program by calling a starter script in the jail with exec.poststart, then you could put the environment variable in the starter script.
It depends on your concrete solution for starting the jail and in which process do you need the variable.
It's for this scenario.

Did a grep for poststart in all /usr/local/etc/qjail* and only found options for poststartssh.
Included a poststart option to /usr/local/etc/qjail.global/nameofjail, like /usr/local/bin/bash /home/myuser/go/goprog, but the program didn't start. If it started, I'd try to set the variable before that invocation.

Where should I place that poststart option when using qjail?
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

Well, this is easy. Instead of calling /usr/local/bin/bash with goprog, create a wrapper script and call the script in poststart:

exec.poststart = "/usr/local/bin/bash /home/myuser/wrapperscript.sh"
Bash:
#!/usr/local/bin/bash

export myvar=....

$SHELL /home/myuser/go/goprog
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

By the way, also: You can try to set the variable directly in the jail.conf. This should also be possible but I have not tested it:

Bash:
exec.poststart += "set myvar ..."
exec.poststart += "/usr/local/bin/bash /home/myuser/go/goprog"
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

Well, this is easy. Instead of calling /usr/local/bin/bash with goprog, create a wrapper script and call the script in poststart:

exec.poststart = "/usr/local/bin/bash /home/myuser/wrapperscript.sh"
Bash:
#!/usr/local/bin/bash

export myvar=....

$SHELL /home/myuser/go/goprog
Calling the goprog under a sub-shell returned an error, either when called as a jail.conf parameter, or when in the jail's command line. I wonder why...
Code:
/usr/home/myuser/go/goprog: 1: Syntax error: Bad escape sequence
/usr/home/myuser/go/goprog: 1: Syntax error: Error in command substitution
But, on the command line, if it's called directly, i.e., ~/go/goprog & it runs fine.


By the way, also: You can try to set the variable directly in the jail.conf. This should also be possible but I have not tested it:

Bash:
exec.poststart += "set myvar ..."
exec.poststart += "/usr/local/bin/bash /home/myuser/go/goprog"
exec.poststart is run on the system environment and that's not what I needed.
When the command is run as exec.start it's run on the jail environment, once again, with no sub-shell.
For the record, just have to edit the file /usr/local/etc/qjail.config/myjail, as I'm using qjail:
Code:
exec.start          =  "/bin/sh /etc/rc";
exec.start         +=  "/usr/home/myuser/go/goprog &";
Thank you very much roccobaroccoSC , SirDice and even to the other user that seemed to have removed the answers.
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

Hi, you have to know what "goprog" is. I assumed it was a bash script.
Use this command to see what type of file it is: file $jailRoot/usr/home/myuser/go/goprog, also see if the executable permissions are set for the file: ls -l $jailRoot/usr/home/myuser/go/goprog. If not, you can set them with chmod a+x $jailRoot/usr/home/myuser/go/goprog.
If it is a binary program or a script with execute permissions, simply start it with its name, don't put /usr/local/bin/bash before it.

Point 2. Yes, true. Use exec.start. Poststart runs outside the jail, it's no good.

So you almost got it. Instead of goprog, run the wrapper script above (but without /usr/local/bin/bash):
Code:
exec.start          =  "/bin/sh /etc/rc";
exec.start         +=  "/usr/local/bin/bash /usr/home/myuser/wrapper_script.sh &";
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

Hi,

I did some modifications because:
  1. although the goprog was working, the environmental variable was not set
  2. I wanted goprog to run under a different user

So in /usr/local/etc/qjail.config/myjail changed exec.start += "/usr/home/myuser/wrapperscript.sh &";
and cat /home/myuser/wrapperscript.sh to:

Code:
  #!/bin/sh
  export ZZZZZZZZ="whatever" && /usr/bin/su - myuser -c '/home/myuser/go/goprog'
Also changed the way I entered the jail, from
qjail console -z myzone -u root -c /usr/local/bin/bash myjail
to
qjail console -z myzone -u root myjail

With all this, I accomplished to enter the jail at SHLVL=1 and to have 2) satisfied.
But the environmental variable ZZZZZZZZ doesn't want be set somehow.

Any ideas?
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

Your script syntax is wrong!
If using /bin/sh, you cannot use export. This is the bash syntax.
Either change the Shebang line to #!/usr/local/bin/bash or use the /bin/sh syntax in the script.

Also - the error messages should be visible in the jail log file. Always read the log to see what's happening.
The log is set in jail.conf via exec.consolelog.

Also - I think you can remove the "&" at the end of exec.start. I don't think it's necessary.
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

Your script syntax is wrong!
If using /bin/sh, you cannot use export. This is the bash syntax.
Either change the Shebang line to #!/usr/local/bin/bash or use the /bin/sh syntax in the script.
I wish it was wrong, but I'm afraid it isn't. You can check the manual of sh(1)

Also - the error messages should be visible in the jail log file. Always read the log to see what's happening.
The log is set in jail.conf via exec.consolelog.
Don't have any errors relating to setting the environmental variable...


The only way it works is to include that information in /etc/profile, like suggested by Wozzeck.Live
I was afraid that it would only work when I entered the jail, as refered by SirDice , but that's not true.
In the usr/local/etc/qjail.config/myjail (that seems to substitute jail.conf) there's a default parameter exec.start = "/bin/sh /etc/rc"; that ensures that /bin/sh is always executed.
So, the environmental variables are visible for every process inside the jail.

Another thing is a variable only seen by some process, but for that I'll have to do some other tests.
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

I wish it was wrong, but I'm afraid it isn't. You can check the manual of sh(1)


Don't have any errors relating to setting the environmental variable...


The only way it works is to include that information in /etc/profile, like suggested by Wozzeck.Live
I was afraid that it would only work when I entered the jail, as refered by SirDice , but that's not true.
In the usr/local/etc/qjail.config/myjail (that seems to substitute jail.conf) there's a default parameter exec.start = "/bin/sh /etc/rc"; that ensures that /bin/sh is always executed.
So, the environmental variables are visible for every process inside the jail.

Another thing is a variable only seen by some process, but for that I'll have to do some other tests.
But see what is going on in the script:
  • first you export the variable
  • then you open a new shell with "su" and the new shell does not have it. sudo deletes the environment.

See for yourself:
Code:
sh
ZZZZZZZZ="whatever"; export ZZZZZZZZ; /usr/bin/su - root -c env | grep ZZZ

# output is empty
I don't think the jail is the problem, you have to get your script right.
Test and debug the script directly in the console without a jail. When you get it right, then install it in the jail.

 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

Again, it depends on what you want to do. If you want the variable to be visible to all the processes, /etc/profile (inside the jaill!) might be a good idea. I don't know though if the file is read only for interactive shells or for all the processes, you need to check that.
If you want to set the variable only for a specific process, I would use a wrapper script.
 
OP
OP
L

lib13

Member

Reaction score: 3
Messages: 97

See for yourself:
Code:
sh
ZZZZZZZZ="whatever"; export ZZZZZZZZ; /usr/bin/su - root -c env | grep ZZZ

# output is empty
I don't think the jail is the problem, you have to get your script right.
Test and debug the script directly in the console without a jail. When you get it right, then install it in the jail.
Removing the ` - ` from the `su` command makes all the difference, as it clears the environment.
So, in the wrapperscript.sh, called from the equivalent `qjail` of jail.conf,
Code:
 exec.start         +=  "/usr/home/myuser/wrapperscript.sh &";
Code:
#!/bin/sh
ZZZZZZZZ="whateverwrapp"; export ZZZZZZZZ; /usr/bin/su myuser -c env | grep ZZZ > /home/myuser/ZZFile
Shows that the value of `ZZZZZZZZ` is indeed written to the file /home/myuser/ZZFile.

So, in conclusion, set the variable in /etc/profile to be seen jail wide. Set it as the above `su` to be set for that process.

The funny thing is that the variable `ZZZZ`, that is set in /etc/profile, doesn't get written to /home/myuser/ZZFile.
 

roccobaroccoSC

Well-Known Member

Reaction score: 96
Messages: 426

If you set the variable in the wrapper script, it would overwrite a variable with the same name from /etc/profile. That's why you see only one value - the variable cannot have two values at the same time.
 
Top