strange rpm --eval command - linux

can someone help me understand what is the purpose of running the following command? what does it do?
$ sudo rpm --eval "%(/bin/bash >&2)"
man rpm gives this:
--eval=’EXPR’
Prints macro expansion of EXPR.
I tried this command, it only shifts user to root, also changed the current
directory of the home directory of user1? why do we want to do this in such a
mysterious way?
[user1#localhost ~]$ sudo rpm --eval "%(/bin/bash >&2)"
root # localhost : /home/user1 $

From: http://rpm.org/user_doc/macros.html
In addition to the “%{…}” form, shell expansion can be performed using
“%(shell command)”. The expansion of “%(…)” is the output of (the
expansion of) … fed to /bin/sh. For example, “%(date +%%y%%m%%d)”
expands to the string “YYMMDD” (final newline is deleted). Note the
2nd % needed to escape the arguments to /bin/date.
Back to your question:
why do we want to do this in such a mysterious way?
You should ask the author. Maybe there is some side effect he wanted to use. Like executing .bashrc.

Related

Command in sudoers file?

I am adding below command in sudoers file, but it is giving me syntax error not allowing "foo=bar" before command.
user ALL=(runas) SETENV:NOPASSWD:foo=bar /path/to/command /path/to/script
If I add using /bin/bash prefix this worked
user ALL=(runas) SETENV:NOPASSWD:/bin/bash -c "foo=bar /path/to/command /path/to/script"
but when I run sudo from user it asks me for a password.
Can someone please let me know How should this work?
Your command list must be a file in your filesystem indicated its full path. I´m not quite sure what your foo=bar "command" should even mean. If that is a variable being set, aren´t you lacking a semicolon (foo=bar;)? But anyways, sudo is not about setting variables either way, it´s about running commands. You should just get rid of foo=bar altogether and keep
user ALL=(runas) SETENV:NOPASSWD: /path/to/command /path/to/script
You wouldn´t use sudo to stop a user from setting a variable (if that is what you even meant in the first place).
from manpages:
A Cmnd_List is a list of one or more command names, directories, and
other aliases. A command name is a fully qualified file name which
may include shell-style wildcards (see the Wildcards section below).

why does "source ~/.profile" keep adding to my $PATH?

This is not a problem affecting me in any way, but just for curiosity...
I have added export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
to my ~/.profile to include a new directory into my bash search.
Then, I ran $ source ~/.profile to reload may shell and I checked my path using $ echo $PATH
The question is:
- why every time I ran source ~/.profile, it appends the same information again,
- how can I clear it?
What I have tried:
- Tried running it multiple times and it keeps adding the same
- Tried to figure out what does the source command does but could not find where it is which source
First question:
why every time I ran source ~/.profile, it appends the same
information again
Simply, source <FILE> does not reload your shell. It only
executes all commands saved in <FILE> as if they were typed directly
by you in the terminal.
Second question:
how can I clear it?
To reload shell open a new terminal
window/tab. Doing just bash or exec bash won't work because a new
process will inherit its parent environment.
Third question:
Tried to figure out what does the source command does but could not
find where it is which source
As I explained once here https://unix.stackexchange.com/a/202326/72304:
All commands that can be run in Bash without typing an explicit path
to it such as ./command can be divided into two parts: Bash shell
builtins and external commands. Bash shell builtins come installed
with Bash and are part of it while external commands are not part of
Bash. This is important because Bash shell builtins are documented
inside man bash and their documentation can be also invoked with help
command while external commands are usually documented in their own
manpages or take some king of -h, --help flag. To check whether a
command is a Bash shell builtin or an external command:
$ type local
local is a shell builtin
It will display how command would be interpreted if used as a command
name (from help type). Here we can see that local is a shell builtin.
Let's see another example:
$ type vim
vim is /usr/bin/vim
In your case:
$ type source
source is a shell builtin
Now we know it's not an external command but a shell bultin (this is why which does not find it) so we need to use help to see what it does:
$ help source
source: source filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
source executes the content of the file passed as argument in the current shell.
It appends the same information again because export is appending a string to PATH, without checking anything (it is not checking if the substring that you want to append is already in the variable).
To avoid appending to PATH every time, you should save the values of your PATH without referring to itself, e.g.:
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/local/go/bin:$GOPATH/bin
Edit:
To check if the directory is already in PATH:
if [[ ":$PATH:" != *":/usr/local/go/bin:$GOPATH/bin:"* ]]; then
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
fi

$0 gives different results on Redhat versus Ubuntu?

I have the following script created by some self-claimed bash expert:
SCRIPT_LOCATION="$(readlink -f $0)"
SCRIPT_DIRECTORY="$(dirname ${SCRIPT_LOCATION})"
export PYTHONPATH="${PYTHONPATH}:${SCRIPT_DIRECTORY}/util"
That runs nicely on my local Ubuntu 16.04. Now I wanted to use it on our RH 7.2 servers; and there I got an error message from readlink; about being called with bad parameters.
Then I figured: on Ubuntu, $0 gives "bash"; whereas on RH, it gives "-bash".
EDIT: script is invoked as . ourscript.sh
Questions:
Any idea why that is?
When I change my script to use a hardcoded readlink -f bash the whole things works. Are there "better" ways for fixing this?
Feel free to also explain what readlink -f bash is actually doing ;-)
As the script is sourced the readlink -f $0 is pointless as it will just show you the command used to run the shell you are currently using.
To explain the difference in command lets look at the bash man page:
A login shell is one whose first character of argument zero is a -, or one started with the --login option.
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.
So guessing ubuntu starts with the noprofile option.
As for readlink, we can again look at the man page
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Therefore it follows symlinks to the base.
Using readlink -f with any non qualified path will result in it just appending the last arg to your current working directory which will not actually show where the script is run.
Try putting any random string instead of bash after it and will see the script is unaffected.
e.g
readlink -f dafsfdsf
Returns
/home/me/testscript/dafsfdsf

Recursively adding bash scripts as commands in Linux?

I'm pretty new to Bash and Linux in general. I've created a couple scripts that I would like to be able to use by typing the command, rather than the directory and the executable file. I'm using Debian Jessie if that makes a difference.
The path to one of my scripts is ~/Scripts/DIR_1/My_Script.sh while another is in ~Scripts/DIR_2/My_Other_Script.sh. I would like ALL of the scripts contained withing the Scripts directory to be indexed as commands regardless of directory/path depth.
I've appended this text to the end of my .bashrc file...
PATH=${PATH}:$(find ~/Scripts -type d | sed '/\/\\./d' | tr '\n' ':' | sed 's/:$//')
Since I'm pretty new to this kind of thing, I had to steal that line from here.
When I try to run My_Script from the command line withing a sub directory of my home folder (or anywhere else for that matter) I get My_Script: command not found
I will readily admit that I might have misunderstood the process of adding a bash script to the command line.
How do I recursively add bash scripts as commands? What is wrong with the process I'm currently using?
I think your issue is that you're not putting the .sh, that is part of your file name.
Normally, pressing tab after having typed only the first letter should complete the command up to the point where there is an ambiguity (or completely if there's none). In case of ambiguity, pressing tab a second time shows the options. So in your case, if you type My<tab><tab> you should have options My_Script.sh and My_Other_Script.sh displayed. And if you type My_Script<tab> it should complete by putting My_Script.sh
Edit
I forgot to precise that you can check the value of PATH by doing echo $PATH. This will allow you to check that the command you copied did what you wanted.

bash:python3.3 no such file or directory

I recently installed a /usr/local copy of python3.3.2 and when convinced it was solid, re-installed under /usr and removed the /usr/local version. When I run the executable as /usr/bin/python3.3, everything is fine but when I run it as 'python3.3' I get the message:
> python3.3
bash: /usr/local/bin/python3.3: No such file or directory
'which' finds /usr/bin/python3.3. I did a 'set -u' and 'set echo' trying to figure out what is going on without success. How is bash getting in here?
Thank you.
Steve S.
Your executable file is still remembered by the shell as if it's done with hash:
hash: hash [-lr] [-p pathname] [-dt] [name ...]
Remember or display program locations.
Determine and remember the full pathname of each command NAME. If
no arguments are given, information about remembered commands is displayed.
-r forget all remembered locations
Running hash -r without needing to restart your shell would fix that.
Update: Actually the shell also remembers it not just by running through hash. Perhaps when you try to execute it or do things like type -P prog, the shell would remember it already. This is the error I had on my test and I didn't run w:
bash: /usr/local/bin/w: No such file or directory
And hash -r fixed it.
It seems like bash is caching the previous location of python3.3 somewhere. Try closing your shell and logging in once again - that should wipe the cache and allow bash to pick up the proper location of python3.3.

Resources