Bash Script Help


Recommended Posts

I have two 200gb drives, on two seperate computers. I have all of my media duplicated on both harddrives. I add media to one of the drives. I want to make a script that will check what media has been added then copy the new media to my other drive via nfs.

I have never made more then three line bash script. These have always been as simple as three consecutive commands. This one will be a challenge, and hopefully fun :-)

The very first thing I would like the script to do is check to see if my nfs share is mounted, if it is not mounted mount it. I was thinking it could check the output of mount or the contents of /etc/mtab. For portability checking the output of mount would be better, because bsd does not use /etc/mtab. My thought was to pipe the output of mount to another command to seach for "192.168.1" . If it found "192.168.1" it could safely assume my nfs share was mounted(or not). Any suggestions on how to do this would be appreciated. Thanks.

edit added later/

maybe awk would be something I would need to use

Link to post
Share on other sites

not done but first part.. need the file copy part.. will get to that tomarrow.. but I am posting incase people have a better way or can add on before I do..

#!/bin/bash


nfs_mount()
{
#replace followng line with you rmoutn command
echo "nfs mount being mounted"
}

nfs_chk ("mount | grep 192.168.1")
if  [ $? ne 0 ]
than
nfs_mount()
fi

# this will see what files are diffrent between the two directorys..
#first being the master second the oenfiles will be copyed to

diff -q /folder1/name/ /folder2/name/ | cut -d ' ' -f4 > /tmp/copy_list

# need to read file /tmp/copy_list and move those files.

Link to post
Share on other sites

To be honest, programming is REALLY out of my element. I need to start from the beginning. I just ordered a used version of "sams shell programming" for $6.50 . I will need to work with that for a while before I start writing(or reading) scritps.

I found this program that should work well for what I wantt to do

http://www.cis.upenn.edu/~bcpierce/unison/

Link to post
Share on other sites

this should do it.. the first was a mix of bash a c++ sorry i was tired...

just change folder names as needed

#!/bin/bash


nfs_mount()
{
#replace followng line with you rmount command
echo "nfs mount being mounted"
}

mount | grep 192.168.1
if  [ "$?" != 0 ];
then
nfs_mount
fi

# this will see what files are diffrent between the two directorys..
#first being the master second the oenfiles will be copyed to

diff -q /folder1/name/ /folder2/name/ | cut -d ' ' -f4 > /tmp/copy_list

# need to read file /tmp/copy_list and move those files.

for i in $( cat /tmp/copy_list ); do
       cp /masterdir/$i /slavefolder/

Link to post
Share on other sites

see your function nfs_mount. what if you have a command in /usr/bin that is also called nfs_mount? will that conflict with the function?

Just for to see what would happen I wrotw this function

#!/bin/bash
rm ()
{
echo "my first function"
echo
echo
echo "this is kind of cool"
echo sure_it_is
}
rm

it worked fine, I thought that because rm was a command it would fail. With the function below I used the name echo, but it failed , WHY?

#!/bin/bashy
echo ()
{
echo "my first function"
echo
echo
echo "this is kind of cool"
echo sure_it_is
}
echo

Link to post
Share on other sites

That function is infinitely recursive: echo calls echo calls echo calls echo ad infinitum.

The first one (rm) works because the shell doesn't care what commands exist in the environment; you define functions that alias utilities till your heart's content. I used to have a function called 'ls' that was defined as something like

ls () { command ls -F $@; }

It behaved just like the ls command except the -F option was always in effect. 'command' causes the shell to bypass any shell functions with the same name, avoiding the infinite recursion you probably hit. '$@' is the list of all the arguments passes to the function. So

ls -la

would be equivalent to

ls -F -la

Edited by jcl
Link to post
Share on other sites

sure, that(echo) should have been obvious.

it seems if any functions are also names of commands in /usr/bin, the comand in /usr/bin is not used, in place of the newly made function.

edit aded later/

this post was made before your explanation

Link to post
Share on other sites
it seems if any functions are also names of commands in /usr/bin, the comand in /usr/bin is not used, in place of the newly made function.

Yup. If I'm reading the Single UNIX spec correctly, commands are looked up in the following places, in order:

  • The list of special shell built-ins.
  • The list of shell functions.
  • The list of commands marked for special handling.
  • The standard path lookup mechanism. Search the directories listed in PATH in order.

The first match is used. The result is that shell functions should always override external utilities.

Edit: This post was written before your edit :)

Edited by jcl
Link to post
Share on other sites

Programming can be a good thing to learn.. one thing I always like about you on the board shanenin is you never seam to fear doing something new..

as for my script.. its missing the done at the end to end the while..

glad it's making sence..

this is where I learned bash from

http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html

Edited by iccaros
Link to post
Share on other sites

mount | grep 192.168.1
if  [ "$?" != 0 ];

the first line of code will either output nothing, or output my nfs share containing that ip address. What does the second line of code do with that info? I understand it is part of an if statement, but I do not understand the condition.

Link to post
Share on other sites

the first line would show a mount point if not ran in a scripts...

(it may need a >> /dev/null to make it not show)

but if the grep is successful (meaning it found 192.168.1) it will return a status of zero (normal good exit status)

the $? is the bash variable for exit status.. so we are checking if the mount | gerp 192.168.1

was a successful (found what it was lookng for ) or failed (with returns a 1)

try it

type mount | grep 192.168.1 >> /dev/null

echo $?

if your mount point is mounted you should see a zero

if not mounted a 1

the != i s a logical not.

so in english

if ["return status of command" is not "zero"];

then

do the following

the fi means to end the if structure (if backwords)

if [ "$?" != 0 ];

Link to post
Share on other sites

I took the plunge. I deleted my 150gb backup media directory off one of my servers. I am now using unison to make a replica of all of my media back to that server. If all gos well, tomarrow morning I will have two servers perfectly synced. Now if I make changes to either server, it will automatically update the other server. I am anxious to see how this all works out :-)

Link to post
Share on other sites

this program, unison, is really cool. It can sync servers on you local system using NFS. It can also sync servers remotely by tunneling using ssh. It also works across platforms window to linux. Another neat feature unlike rysync, you can make changes to either server(not the master server only) then the changes will get updated to the other server.

I am still working out some bugs, but I am pretty sure it will work like it is supposed to.

Link to post
Share on other sites

I decided to make a script that would mount my nfs share before running unison. This way I wont ever forget to mount it. I think that would screw up my syncing. Thanks for the help(iccaros and jcl), this is my first attempt at programming(term used very loosely)

#!/bin/sh

mount | grep 192.168.1
if [ "$?" != 0 ];
then
 echo "mounting nfs share"
 mount_nfs 192.168.1.104:/mnt/media /home/shane/freevo
else
 echo "nfs already mounted, proceeding to sync your servers"
fi

mount | grep 192.168.1
if [ "$?" = 0 ]
then
 echo "preparing to run unison"
 # the following line gives the command to sync my two servers
 /usr/bin/unison /home/shane/freevo /mnt/media
else
 echo "nfs failed to mount. exiting"
fi

Link to post
Share on other sites

this line produces output to my shell, which I do not want. Is there a way to keep this line from making output

mount | grep 192.168.1

edit added later/

I just piped it like this, this seems like an ok solution

mount | grep 192.168.1 | if [ "$?" != 0 ];

Link to post
Share on other sites

For future reference

some-command >/dev/null

with redirect output to the bit bucket. Also, this seems to work

if mount | grep 192.168.1 >/dev/null
then
   # and so on

if like me you're afraid of $? :)

Link to post
Share on other sites
I decided to make a script that would mount my nfs share before running unison. This way I wont ever forget to mount it. I think that would screw up my syncing. Thanks for the help(iccaros and jcl), this is my first attempt at programming(term used very loosely)

#!/bin/sh

mount | grep 192.168.1
if [ "$?" != 0 ];
then
 echo "mounting nfs share"
 mount_nfs 192.168.1.104:/mnt/media /home/shane/freevo
else
 echo "nfs already mounted, proceeding to sync your servers"
fi

mount | grep 192.168.1
if [ "$?" = 0 ]
then
 echo "preparing to run unison"
 # the following line gives the command to sync my two servers
 /usr/bin/unison /home/shane/freevo /mnt/media
else
 echo "nfs failed to mount. exiting"
fi

JCL writes much better code..

so I have only one thing to add..

you should check to see if nfs mouted again after mounting .. that way no need to do it before runnnig the command..

they way you did it great .. even more so if you want to reuse code. (ie insted of a function make it a scritp and call the script)

then anytime you need a script to check and mout the nts share they just call the script to do it..

I'll write up an example when I get a little time today..

good work.

Link to post
Share on other sites
you should check to see if nfs mouted again after mounting .. that way no need to do it before runnnig the command..

that is what I originally was trying to do(originally I was using a function), but things were not flowing correctly. The more I tried to fix it, the more ugly it got. So I scrapped everything and started fresh, and came out with the code listed above.

Link to post
Share on other sites

ya that is how I write also..

Link to post
Share on other sites

I wrote this revised script on my bsd workstation. It seems to run well

#!/bin/sh

check-nfs ()
{
echo "checking"
mount | grep 192.168.1 > /dev/null
if [ "$?" = 0 ]
then
  echo "NFS is mounted"
  return 0
else
  echo "NFS is not mounted"
  return 1
fi
}

mount-nfs ()
{
echo "mounting NFS"
mount -t nfs 192.168.1.104:/mnt/media /home/shane/freevo
}

run-unison ()
{
echo "preparing to run unison"
/usr/local/bin/unison -version
exit 0
}

echo "NFS needs to be mounted before sycing can begin"
check-nfs
if [ "$?" = 0 ]
then
  run-unison
else
  mount-nfs
  check-nfs
fi

if [ "$?" = 0 ]
then
  run-unison
else
  echo "NFS failed to mount. exiting"
fi

the problem comes when I port it over to my linux freevo box. I am getting this error

freevo2 root # freevosync
/usr/local/bin/freevosync: line 15: `check-nfs': not a valid identifier

Link to post
Share on other sites

for portability, I used #!/bin/sh instead of #!/bin/bash . This way the script shuld run on a bsd box that does not have bash installed. Linux just makes a link form /bin/sh to /bin/bash, but......

I got my script to work on my linux box by changeing #!/bin/sh to #!/bin/bash , how could that be? Why should that make any difference?

Link to post
Share on other sites

POSIX only permits shell function names containing alphanumeric characters and underscores; hyphens and other punctuation are verboten. When bash is invoked as sh it tries to strictly follow POSIX and historical sh; apparently that extends to the naming restrictions.

Addendum: took me a while to find it, but that is documented behavior in the Bash POSIX Mode section of the manual, item 15. For details

$ info bash 'Bash Features' 'Bash POSIX Mode'

Edited by jcl
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...