Ok, this is going to be an article for beginners but with a spin at the end even for the most advanced users. Let's say you want to run a command inside of chroot as another user all in a single command and be back at your shell. How do you do it? Turns out it can be easily done by combining several commands in a beautiful way:

sudo chroot /chroot su - user -c "cmd args"

It may seem a pretty crazy combination of commands but it's all really easy to undestand. First, let's take a look at man chroot. It says,

sudo chroot /chroot command

Okay, so we can run command inside of chroot as root, but how do we run the command inside of chroot as another user? How about using su for command? Let's try that:

sudo chroot /chroot su - user

This runs su inside of chroot as user but we get an interactive shell. Let's take a closer look at man su. It says that we could try:

sudo su - user -c "cmd args"

This runs the cmd args through the shell. Great! So let's use this together with chroot again:

sudo chroot /chroot su - user -c "cmd args"

Excellent! Almost what we needed. However there is still one small problem. If the user has a custom environment (such as different PATHs to executables or some other customizations), it won't get initialized, so we've to source the initialization file(s) ourselves:

sudo chroot /chroot su - user -c ". ~/.bash_profile; cmd args"

This does what we wanted and runs cmd args inside of chroot located at /new-root-path as user and after running the command it quits and we're back at our shell.

What a beautiful way to combine commands!

On Sourcing ~/.bash_profile

Some people couldn't understand why I was sourcing ~/.bash_profile. The reason is because I was unable to find another way to invoke the login shell and have the environment initialized.

I tried this:

sudo chroot /chroot su -l user -c "cmd args"

And it just wouldn't execute ~/.bash_profile. Su's man page says that -l invokes a login shell, however I don't see that happening. Here's the transcript that demonstrates it:

pkrumins$ pwd
/chroot

pkrumins$ sudo cat ./home/testuser1/.bash_profile 
echo "moo"
PATH="/test/bin"

pkrumins$ sudo chroot /chroot su -l testuser1 -c 'echo $PATH'
/bin:/usr/bin

pkrumins$ sudo chroot /chroot su -l testuser1 
moo

testuser1$ echo $PATH
/test/bin

testuser1$ ^D
logout

pkrumins$ sudo chroot /chroot su -l testuser1 -c '. ~/.bash_profile; echo $PATH'       
moo
/test/bin

pkrumins$ sudo chroot /chroot su -l testuser1
moo

testuser1$ /bin/bash -l -c 'echo $PATH'
moo
/test/bin

This definitely looks like a bug in su to me when -l and -c are used together. So the only way to get the environment loaded is by sourcing the initialization files yourself.

Update

I went through su's source code (can be found in util-linux package) and it turns out it's not a bug in su!

Here are the arguments that su passes to execv when I run su user -c 'echo $PATH' (see run_shell function in su.c):

shell: /bin/bash
args[0]: -bash
args[1]: -c
args[2]: echo $PATH

As you can see, args[0][0] is -, which makes bash a login shell, so bash should be executing the startup files, but it does not!

To figure out what was happening, I built a custom version of bash and added a bunch of debugging statements. I found that there are two different login-shell states! Who'd have thought? One that you get when you've set args[0][0] to -, the other that you get when you've used the -l argument (to bash, not su!).

In case args[0][0] is -, and you're using -c to execute code, bash will not execute startup files because it's in this "non-interactive positive-login-shell" state. However if you use -l and -c, it goes into "non-interactive negative-login-shell" state, and it will execute startup files (see run_startup_files function in bash's shell.c source file).

That was one hell of an adventure debugging this. So if you want bash to execute startup files through su, use my ". ~/.bash_profile" sourcing trick! (Or define NON_INTERACTIVE_LOGIN_SHELLS when building bash).

Comments

lava Permalink
December 24, 2012, 16:58

> su - user sh -c ". ~/.profile; command args"

... I have no words.

su user -c ". ~/.profile; command args"

December 24, 2012, 20:00

Oh well, I missed that "-c" calls the commands via shell.

wjgeorge Permalink
December 25, 2012, 17:06

well fix the code in the article.

not sure why you're just not doing a 'sudo -u user cmd'

December 25, 2012, 17:19

Because then the cmd will not run inside of chroot.

dkr Permalink
December 24, 2012, 17:26

looks pretyt much the same?

Qwerty Uiop Permalink
December 24, 2012, 19:15

I am not convinced you understand what you're talking about. This isn't the first time I've unwittingly clicked a useless and uninformed submission you spammed on HN.

December 24, 2012, 20:01

I'm sorry that you don't find the articles interesting. Other people find them pretty compelling. Don't click the links unwittingly next time!

December 25, 2012, 09:28

"I am too dumb to understand this article, therefore the author must be clueless." I don't know if there is a fancy latin name for this logical fallacy, but I like to call it "Christ, what an asshole."

wjgeorge Permalink
December 25, 2012, 17:07

actually I agree with qwerty

no need for your attack.

urfag Permalink
December 25, 2012, 19:25

fag

December 25, 2012, 05:39

You do great work Peteris. I appreciate every post you have on your site. Keep up the great work and thanks for sharing.

December 25, 2012, 14:17

Thank you!

lkjasdf Permalink
December 25, 2012, 05:58

There is a severe disconnect between your self-image and reality.

December 25, 2012, 14:17

Said lkjasdf.

Sharif Olorin Permalink
December 26, 2012, 00:04

A login shell should source ~/.bashrc, to the best of my knowledge and experience. What environment are you using/what specifically in your .bashrc are you noting doesn't get executed?

yrougy Permalink
December 26, 2012, 09:26

Nope ! The behavior is:
Login shell -> profile
Non-login shell -> ressource file (.bashrc)

It's either one or the other.

However, most distros puts a profile with something like

if [ -f ~/.bashrc ]
then
. ~/bashrc
fi

which "manually" source the rc file if it exists. This is the best way to keep things proper (environment goes to profile and variable non exported to the ressource file this way, so aliases or PS1 goes to the rc file and are usable even in a login shell).

Y.

December 27, 2012, 18:41

It's a bug in su. I just updated the article at the that demonstrates it.

Update: it's actually not a bug in su. Check out the last update.

March 11, 2014, 17:40

I should read more on this topic. I am really very happy for providing the nice info in this website that to using the great technology in this website. I had really like it very much for visiting the nice info in this website. This info is simple to understand the normal people also.

yrougy Permalink
December 26, 2012, 09:21

You have to source .bashrc because, in case of a login shell, the bash process only loads the profile (/etc/profile, ~/.profile and/or ~/.bash_profile ) . The *profile may loads the ressource file by itself, but it's up to you to do so.

In case of a non-interactive shell, the bash process *doesn't* look for the ~/.bashrc specifically. Actually it searches for a environment variable BASH_ENV to know the ressource file to loads.

Y.

December 27, 2012, 19:59

That's right. However I discovered it was a bug in su. If you use su with -c and -l, it will not spawn the shell as a login shell.

Update: it's actually not a bug in su. Check out the last update.

Maxim Yegorushkin Permalink
December 26, 2012, 20:06

The way you pass commands to the shell may require akward quoting. Just pipe the commands into the shell. See http://stackoverflow.com/a/3435460/412080

jaysunn Permalink
January 01, 2013, 14:02

peteris,
I really enjoy your posts? Please do not let the trolls bite.. Keep the great tips coming.

Happy New Year!!!

January 02, 2013, 23:08

Happy new year!

January 07, 2013, 10:38

but what's the difference of positive-login-shell and negative-login-shell?

January 08, 2013, 13:36

Peteris Krumins,
I really appreciate your posts. Please do not give up listening to those dumb people. Keep on posting.
Happy New Year.

sapphirecat Permalink
April 11, 2013, 18:35

Random thought: if your working directory is already /chroot, you can use the current-dir syntax to expand the path: sudo chroot ~+ su ....

Manh Cuong Le Permalink
May 15, 2013, 15:30

Hi, Peteris Krumins.

This is a very nice article. But I have trouble in understanding what is "positive-login-shell" and "negative-login-shell".

Please give it more details.

its cool and keep posting,thank you

August 06, 2013, 07:05

I really appreciate your posts. Please do not give up listening to those dumb people.

poppinfresh Permalink
August 26, 2013, 21:14

This is not terribly safe and negates the purpose of using chroot. You want to remove all setuid binaries and interactive shells from a chroot environment.

September 11, 2013, 05:51

commanding is not easy job in real sa well as in computer the above article give the good guidlines about the commands or may be i search these type of the material its a example of commanding in software.

You do great work Peteris. I appreciate every post you have on your site

October 28, 2013, 09:21

It is really helpful for students like me in availing of the academic writing services that this site have. I could have failed one of my subject if I did not found out about this website. Thank you very much to the writer in this site that helped me regarding my academic writing problems.

October 28, 2013, 11:14

I could not agree no more with Sam.
home page I will be happy if you agree with me

Aoto Permalink
February 16, 2014, 18:37

That’s once we begin to grasp one another deeply. As they assert we have a tendency to become like associate open book to the person whom we've trustworthy . it's not associate nightlong method, it takes time and confidence. Room Share.

August 29, 2014, 09:40

lets try

Thanks a lot

October 15, 2014, 14:18

This site has perfect content. Thank you for your nice site

December 09, 2014, 09:49

nice
a href=" http://mynycstreets.com/2014/12/download-lingaa-movie-torrentlingaa-movie-free-download/">Lingaa Movie Torrent Downl

<oad>

lingaa movie in mp4lingaa movie in hdlingaa movie in free downloadLingaa Movie download in torrentfree download lingaa movie
diggnice article

Diana Permalink
December 17, 2014, 16:19

This article is quite helpful and informative too. I enjoyed a lot. Thanks for sharing such a great article.

Beautiful Christmas Quotes for your friends and family...
christmas quotes
Christmas Messages for Whatsapp

Best Christmas Greetings for your friends and family...
christmas greeting
christmas wishes

What to Write in Christmas Card....... Check out best Christmas Greeting Card Words
What to Write in Christmas Card

Get Beautiful and Unique Christmas Wallpapers for free
free christmas wallpaper
christmas tree decorating ideas

Thanks for sharing such a great article.

Leave a new comment

(why do I need your e-mail?)

(Your twitter name, if you have one. (I'm @pkrumins, btw.))

Type the word "network_365": (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.

Advertisements