Alright guys, so I try to install rvm in a docker container based on ubuntu:14.04. During the process, I discovered that some people do something like this to ensure docker commands are also run with the bash:
RUN ln -fs /bin/bash /bin/sh
Now The weirdness happens and I hope someone of you can explain it to me:
→ docker run -it --rm d81ff50de1ce /bin/bash
root#e93a877ab3dc:/# ls -lah /bin
....
lrwxrwxrwx 1 root root 9 Mar 1 16:15 sh -> /bin/bash
lrwxrwxrwx 1 root root 9 Mar 1 16:15 sh.distrib -> /bin/bash
...
root#e93a877ab3dc:/# /bin/sh
sh-4.3# echo $0
/bin/sh
Can someone explain what's going on here? I know I could just prefix my commands in the dockerfile w/ bash -c, but I would like to understand what is happening here and if possible still ditch the bash -c prefix in the dockerfile.
Thanks a lot,
Robin
It's because bash has a compatibility mode where it tries to emulate sh if it is started via the name sh, as the manpage says:
If bash is invoked with the name sh, it tries to mimic the startup
behavior of historical versions of sh as closely as possible, while
conforming to the POSIX standard as well. When invoked as an
interactive login shell, or a non-interactive shell with the --login
option, it first attempts to read and execute commands from
/etc/profile and ~/.profile, in that order. The --noprofile option
may be used to inhibit this behavior. When invoked as an interactive
shell with the name sh, bash looks for the variable ENV, expands its
value if it is defined, and uses the expanded value as the name of a
file to read and execute. Since a shell invoked as sh does not
attempt to read and execute commands from any other startup files, the
--rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When
invoked as sh, bash enters posix mode after the startup files are
read.
Related
This question already has answers here:
bash recursive xtrace
(2 answers)
Closed 11 months ago.
I have a linux system that uses lots of bash scripts as the bootup scripts. I want to print all the bash statements that are being executed in order to debug some issue. How can I do that at system-wide level?
I had the following as init in my system :
$ls -la /init
lrwxrwxrwx. 1 root root 20 Feb 10 04:46 /init -> /lib/systemd/systemd
I replaced init with a script like below :
#!/bin/bash
set -x
/lib/systemd/systemd
but no prints.
Download bash sources, change https://github.com/bminor/bash/blob/f3a35a2d601a55f337f8ca02a541f8c033682247/flags.c#L88 to echo_command_at_execute = 1. echo_command_at_execute might be reset somewhere later, in reset_shell_flags() and with change_flag('x', 0) - make echo_command_at_execute const and remove all assignments to it. Recompile and install. Create sh -> bash symlinks appriopriate for your system.
Note, that some scripts may parse stderr output of some shell programs. This modification may result in unstable system.
Copy /bin/bash to for example /bin/bash2, and similar with sh. Create an executable script:
#!/bin/bash2
/bin/bash2 -x "$#"
Repeat the process for sh. The paths have to be absolute.
Note, that for initrd you will have to regenerate it and include the copied executables and the scripts in the image. the copied executables in the image. Research your distribution specific ways about generating initrd.
I give an idea that do not confirm:
mv /bin/bash /bin/bashx
vi /bin/bash
/bin/bashx -x $#
The below script executing with root user.After switch user Unix function showing error.
test.sh
#!/bin/bash
fn_test()
{
echo "This is function"
}
whoami
fn_test
su - oracle<<EOF
whoami
fn_test #This function not called
EOF
exit 0
O/P
root $ ./test.sh
root
This is function
oracle
-ksh[2]: fn_test: not found [No such file or directory]
You have a confusion on what su actually does: you hope it to just swith user when it does start a new process. You can control it with ps in an interactive session: you see the original shell, the su command, the new shell launched by su and the current ps command.
As a shell function is local to the shell it cannot be used in a (grand) child shell.
The best that you can hope is to pass something through the environment. I know that aliases can be put there unsure for functions. Moreover, this is absolutely shell dependant and might not be portable.
I installed debian strech yesterday. I installed fish shell . I change the default shell to fish by the following
su chsh -s 'which fish'
Then again enter the this command
su chsh -s `which fish`
Now after I restart the PC I encountered the following error while using "su"
sathish#localhost ~> su
Password:
Cannot execute which fish: No such file or directory
Did you mean to use regular single-quote chars in your first command? Doing so means your shell is now literally the string which fish rather than the path to the fish command. That explains why your second command reports that it cannot execute "which fish". Even without that mistake it is a really bad idea to change the default shell for your root account. You're just asking for trouble. And I say that as a core fish developer. Unless you are an extremely competent and confident CLI user you should not change the root shell. You can always do exec fish -l after su if you want fish as your root shell.
(I'm new in shell script.)
I've been stuck with this issue for a while. I've tried different methods but without luck.
Description:
When my script attempt to run another script (SiebelMessageCreator.sh, which I don't own) it prompts:
-bash: ./SiebelMessageCreator.sh: No such file or directory
But the file exists and has execute permissions:
-rwxr-xr-x 1 owner ownergrp 322 Jun 11 2015 SiebelMessageCreator.sh
The code that is performing the script execution is:
(cd $ScriptPath; su -c './SiebelMessageCreator.sh' - owner; su -c 'nohup sh SiebelMessageSender.sh &' - owner;)
It's within a subshell because I first thought that it was throwing that message because my script was running in my home directory (When I run the script I'm root and I've moved to my non-root home directory to run the script because I can't move my script [ policies ] to the directory where the other script resides).
I've also tried with the sh SCRIPT.sh ./SCRIPT.sh. And changing the shebang from bash to ksh because the SiebelMessageCreator.sh has that shell.
The su -c 'sh SCRIPT.sh' - owner is necessary. If the script runs as root and not as owner it brokes something (?) (that's what my partners told me from their experience executing it as root). So I execute it as the owner.
Another thing that I've found in my research is that It can throw that message if it's a Symbolic link. I'm really not sure if the content of the script it's a symbolic link. Here it is:
#!/bin/ksh
BASEDIRROOT=/path/to/file/cpp-plwsutil-c
ore-runtime.jar (path changed on purpose for this question)
java -classpath $BASEDIRROOT com.hp.cpp.plwsutil.SiebelMessageCreator
exitCode=$?
echo "`date -u '+%Y-%m-%d %H:%M:%S %Z'` - Script execution finished with exit code $exitCode."
exit $exitCode
As you can see it's a very siple script that just call a .jar. But also I can't add it to my script [ policies ].
If I run the ./SiebelMessageCreator.sh manually it works just fine. But not with my script. I suppose that discards the x64 x32 bits issue that I've also found when I googled?
By the way, I'm automating some tasks, the ./SiebelMessageCreator.sh and nohup sh SiebelMessageSender.sh & are just the last steps.
Any ideas :( ?
did you try ?
. ./SiebelMessageCreator.sh
you can also perform which sh or which ksh, then modify the first line #!/bin/ksh
I've got a shell script which I am trying to run as a specific user. My command looks like this:
su - jetty sh ./runProgram.sh
When I attempt to run this command through the console I get an error saying:
/bin/sh: /bin/sh: cannot execute binary file
I also tried:
su - jetty sh runProgram.sh
And I still get the same error..
It DOES work if I do this:
sh runProgram.sh
But this shell script is meant to be run by a specific user. Any advice on how to get this working??
Try
su - jetty -c sh runProgram.sh
According to su's documentation (info coreutils 'su invocation'), it will by default execute a shell, and the arguments to su are passed as arguments to the shell.
The implication is simply this: su is doing in essence:
/bin/sh *arguments_to_su*
but it does it as another user (the "effective user id")... that's all... So
su - jetty sh ./runprogram.sh
is akin to
(become the user jetty via login or su)
/bin/sh sh ./runprogram.sh
...and the shell will report an error, because the first /bin/sh, called by su, is trying to run the program sh as a shell script, with ./runprogram.sh as its argument. But sh itself is not a shell script, it is a binary (whose job it is is to run shell scripts).
if you were to simply do this:
su - jetty ./runprogram.sh
Then the su command will call /bin/sh with the program ./runprogram.sh as its argument, and jetty as the effective user id, and all should be well. ...SHOULD be well, because since you are doing an su - you are making the shell a login shell and changing to the user's home directory. If runprogram.sh is not in the home directory, you will get an error.
This is why, also, you cannot run for example run a cp command by simply:
su - jetty cp file1 file2
...because, again, after su changes effective user id to jetty it will try this:
/bin/sh cp file1 file2
...and cp is not a shell script. But the -c option works in this case; because you are telling su that you want to run /bin/sh with the -c option to the shell:
su - jetty -c "cp file1 file2"
does the job. Note that you must quote the command, because the entire string is passed to the shell and (I believe) any following arguments are ignored.
Finally, the previous poster's answer doesn't work for me on Linux, it requires the entire command string to be quoted.