Directory structure variations in bash script - linux

I have a shell script myautoappupgrade.sh where I automate a process of application upgrade. The script has to be run on few different servers. Unfortunately, the application is located in slightly different directory on each server - the number for parent directory varies between 1-20. How I can modify the script, so that the directory can be replaced by some sort of variable? I don't want to edit the script for each server because there are many directory queries in the automation script.
example:
cd /ae1/apps/myapp/upgradefiles/
unzip file.zip
./install.sh
the directory slightly changes on another server:
cd /ae2/apps/myapp/upgradefiles/
unzip file.zip
./install.sh
and another..
cd /ae3/apps/myapp/upgradefiles/
unzip file.zip
./install.sh

Try something like this:
#!/bin/bash
num=$1
cd /ae${num}/apps/myapp/upgradefiles/file.zip
unzip file.zip
./install.sh
Then call the script with the number as first argument:
myautoappupgrade.sh 1

The simple and obvious solution is to not hard-code the directory at all. Modify the script so it accepts the parent directory as an argument, or just cd into the parent directory before running the script.
Perhaps something like this:
while read server dir; do
ssh "$server" "cd '$dir' && unzip apps/myapp/upgradefiles/file.zip/file.zip && ./install.sh"
done <<\:
ernie /ae1
bert /ae2
cookiemonster /home/cmonster/anN
:
It would probably be even better if you unzipped into a temporary directory, but hopefully this should get you moving in the right direction.
Of course, if you can be sure that /ae[0-1] is always there and there is only one match,
cd /ae[0-9]/apps/myapp/upgradefiles/file.zip
would do what you are asking.
(Do you really have a file named file.zip inside a directory also named file.zip? I'm guessing actually take away the file.zip from the end of the cd path.)

By simply using:
cd /ae*/apps/myapp/upgradefiles/
The * will expand any character.

Related

How to execute from any directory Bash script that sources other Bash scripts (not using path variable)

I am not trying to execute a Bash script from any directory by adding the script to my Path variable.
I want to be able to execute the script from any directory using the directory path to that file ... but the file I want to execute sources other files, that is the problem.
If I am in directory file with two scripts myFunctions.sh and sourceFunctions.sh
sourceFunctions.sh
#!/bin/bash
source ./myFunctions.sh
echoFoo
myFunctions.sh
function echoFoo()
{
echo "foo"
}
I can run myFunctions.sh and foo will print to console, but If I go up a directory and run myFunctions.sh I get error
cd ..
file/sourceFunctions.sh
-bash: doFoo.sh: command not found
Unless I changed source file/myFunctions.sh to source file/myFunctions.sh in sourceFunctions.sh.
So how can I source independent of my working directory so I can run sourceFunctions.sh from any working directory I want?
Thanks
You have the right idea. Doesn't need to be that complicated though:
source `dirname $0`/myFunctions.sh
I often compute "HERE" at the top of my script:
HERE=`dirname $0`
and then use it as needed in my script:
source $HERE/myFunctions.sh
One thing to be careful about is that $HERE will often be a relative path. In fact, it will be whatever path you actually used to run the script, or "." if you provided no path. So if you "cd" within your script, $HERE will no longer be valid. If this is a problem, there's a way (can't think of it off hand) to make sure $HERE is always an absolute path.
I ended up just using a variable of the directory path to the script itself for the source directory
so
#!/bin/bash
source ./myFunctions.sh
echoFoo
becomes
#!/bin/bash
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
source ${SCRIPTPATH}/myFunctions.sh
echoFoo
source

Move script.sh to bin

I'm new to shell programming and I'm trying to create a simple script that gives me some infos on the status of the machine (i.e date, time, users logged in etc) on Scientific Linux 6 (I know it's old, but the department of my university runs on it so there's no escaping)
Basically I've created my script "sysinfo.sh"
#!/bin/sh
....
exit 0
as root user I want to move it so that I can be able to execute it anywhere and I thought the right way to do it was
sudo mv sysinfo.sh usr/local/bin
but I get the error message
mv: cannot move `sysinfo.sh' to `usr/local/bin': No such file or directory
then I looked for the PATH and it gives me
$ echo $PATH
/u/geo2/sw//System/tools/bin:/usr/bin:/bin
What is the right place to move my script?
Best practice for these kind of manipulation or learning is to have scripts in your $HOME/bin directory.
mkdir $HOME/bin
export PATH=$PATH:$HOME/bin
mv sysinfo.sh $HOME/bin
chmod +x $HOME/bin/sysinfo.sh
If you anyway want to move it to /usr/local/bin, why not do that with:
sudo mv sysinfo.sh /usr/local/bin
chmod +x /usr/local/bin/sysinfo.sh
chmod command will make the script executable.
from chmod man:
x -- The execute/search bits.
The command that you posted indicates that you were trying to use the absolute path for copying, but you missed a leading slash --
the directory should be /usr instead of usr.
Try
sudo mv sysinfo.sh /usr/local/bin
Note that unless an absolute path is specified, the shell looks for the path relative to the current working directory.
In this case, the shell was looking for the subdirectory usr under the current directory which was not found;
hence the error message.
Thank you very much!
In the end, I didn't realize that the directory /usr/local/bin wasn't in the PATH
So i just needed to
export PATH=$PATH:/usr/local/bin
sudo mv sysinfo.sh /usr/local/bin
:D

How do you run bash script as a command?

I have a bash script, which I use for configuration of different parameters in text files in my wireless access media server.
The script is located in one directory, and because I do all of configurations using putty, I have to either use the full path of the file or move to the directory that contains the file. I would like to avoid this.
Is it possible to save the bash script in or edit the bash script so that I can run it as command, for example as cp or ls commands?
The script needs to be executable, with:
chmod +x scriptname
(or similar).
Also, you want the script to be located in a directory that is in your PATH.
To see your PATH use:
echo $PATH
Your choices are: to move (or link) the file into one of those directories, or to add the directory it is in to your PATH.
You can add a directory to your PATH with:
PATH=$PATH:/name/of/my/directory
and if you do this in the file $HOME/.bashrc it will happen for each of your shell's automatically.
You can place a softlink to the script under /usr/local/bin (Should be in $PATH like John said)
ln -s /path/to/script /usr/local/bin/scriptname
This should do the trick.
You can write a minimal wrapper in your home directory:
#!/bin/bash
exec /yourpath/yourfile.extension
And run your child script with this command ./NameOfYourScript
update: Unix hawks will probably say the first solution is a no-brainer because of the additional admin work it will load on you. Agreed, but on your requirements, my solution works :)
Otherwise, you can use an alias; you will have to amend your .bashrc
alias menu='bash /yourpath/menuScript.sh'
Another way is to run it with:
/bin/bash /path/to/script
Then the file doesn't need to be executable.

Is threadsafe using `cd path/ && zip -r name.zip directory/`

I would like to zip a directory, but I need to use a full path and I need that the zip files starts in the directory, not in /.
That question was solved here: Command to zip a directory using a specific directory as the root
The answer would be basically to use this:
If I want to zip full/path/to/directory/ in a file named myFile.zip, I would need to use the command
cd /full/path/to/ && zip -r myFile.zip directory/
Now, my question: is this threadsafe? without && (2 commands) would be unsafe, is && enough to make it threadsafe?
Saying command1 && command2 implies that command2 would be executed only if command1 exits with a return code of zero. If /full/path/to/ doesn't exist than the zip command wouldn't be executed.
Regarding the thread safety part, if you have multiple processes trying to create a file with the same name in a given directory, chances are that it'll lead to unexpected results.

One command to create and change directory

I'm searching for just one command — nothing with && or | — that creates a directory and then immediately changes your current directory to the newly-created directory. (This is a question someone got for his exams of "linux-usage", he made a new command that did that, but that didn't give him the points.) This is on a debian server if that matters.
I believe you are looking for this:
mkdir project1 && cd "$_"
define a bash function for that purpose in your $HOME/.bashrc e.g.
function mkdcd () {
mkdir "$1" && cd "$1"
}
then type mkdcd foodir in your interactive shell
So stricto sensu, what you want to achieve is impossible without a shell function containing some && (or at least a ; ) ... In other words, the purpose of the exercise was to make you understand why functions (or aliases) are useful in a shell....
PS it should be a function, not a script (if it was a script, the cd would affect only the [sub-] shell running the script, not the interactive parent shell); it is impossible to make a single command or executable (not a shell function) which would change the directory of the invoking interactive parent shell (because each process has its own current directory, and you can only change the current directory of your own process, not of the invoking shell process).
PPS. In Posix shells you should remove the functionkeyword, and have the first line be mkdcd() {
For oh-my-zsh users: take 'directory_name'
Reference: Official oh-my-zsh github wiki
Putting the following into your .bash_profile (or equivalent) will give you a mkcd command that'll do what you need:
# mkdir, cd into it
mkcd () {
mkdir -p "$*"
cd "$*"
}
This article explains it in more detail
I don't think this is possible but to all people wondering what is the easiest way to do that (that I know of) which doesn't require you to create your own script is:
mkdir /myNewDir/
cd !$
This way you don't need to write the name of the new directory twice.
!$ retrieves the last ($) argument of the last command (!).
(There are more useful shortcuts like that, like !!, !* or !startOfACommandInHistory. Search on the net for more information)
Sadly mkdir /myNewDir/ && cd !$ doesn't work: it retrieves the last of argument of the previous command, not the last one of the mkdir command.
Maybe I'm not fully understanding the question, but
>mkdir temp ; cd temp
makes the temp directory and then changes into that directory.
mkdir temp ; cd temp ; mv ../temp ../myname
You can alias like this:
alias mkcd 'mkdir temp ; cd temp ; mv ../temp ../'
You did not say if you want to name the directory yourself.
cd `mktemp -d`
Will create a temp directory and change into it.
Maybe you can use some shell script.
First line in shell script will create the directory and second line will change to created directory.

Resources