Shell script for remote servers

Hi ,

I have written a small script :

set -x
#!/bin/ksh
for i in `cat /tmp/list` ( list contains remove servers )
do
ssh -t $i << EOF
uname -a
cd ~user
echo "Enter the dir >"
read dir
path=`ll -ld /home/user/"$dir"`
if [ "$dir" -eq "$path" ]; then
echo "Dir exists "
read
rm $path
else
echo "no such file"
fi
#echo $?
#rm test
#pwd
EOF
read
logout
done

The idea is to have a interactive script to delete directory under /home/user/ area from all the remote servers via ssh .. I have created list of server in /tmp/list to call the same in for loop. The problem is that the script does not work interactively and completes the entire loop for all servers without taking any options. Please provide your valuable inputs

Thanks
Kpatel.

The read command is trying to use stdin which is used by the here document (<< EOF). I would suggest trying something like this:

...
  ssh "$i" "$(
  cat << EOF
    uname -a
    cd ~user
    echo "Enter the dir >"
    read dir
    ......
EOF
  )"
......
1 Like

A few issues to tweak first:-

  • The set -x line will negate the 'shebang' line which forces the code to run under ksh. You may get away with it if you are running ksh as your shell already.
  • Some indenting you make it much clearer.
  • Wraping your code with
    ~~~
    text &
    ~~~
    tags will make it far easier to read and preserve the spacing for indenting or fixed width data.
  • You have what is known as a UUOC for your loop. I have a better way shown in green
  • The variable i is not very descriptive. Usually better to have a sensible name for variables so you can read your code as a natural language.
  • You use ll -ld where ll is an alias, often to ls -l but this output would surely never match what is being keyed in.
  • You prompt and read as two commands. There is a ksh way to do this in one shown in blue.

With indenting and the other adjustments, I get your code to be:-

#!/bin/ksh
set -x

while read servername          # File read at the done statement
do
   ssh -t $servername << EOF
   uname -a
   cd ~user
   read dir?"Enter the dir >"
   path=`ll -ld /home/user/"$dir"`
   if [ "$dir" -eq "$path" ]; then
      echo "Dir exists "
      read
      rm $path
   else
      echo "no such file"
   fi
   #echo $?
   # rm test
   #pwd
EOF

read
logout
done < /tmp/list

I must admit I am confused.

It's an automated process, but you seem to prompt for input. The ssh and the embedded read statements will be gobbling up your input for the file the way you had it, however I'm struggling to work out the purpose overall.

Can you elaborate on the logical you are trying to achieve. I've got:-

  • For every server in a list (file), connect and:-
    [list]
  • Display the OS information
  • Change to the home directory of user user (if it exists)
  • Prompt for a directory, then try to match that to the current directory in an odd way
  • If it matches, delete the current directory whilst still in it (?) after pressing ENTER with no chance to escape.
  • If it doesn't match, just display a message
  • Disconnect ungracefully by terminating the input (EOF)
  • After pressing ENTER, logout! - oh, everything will exit, perhaps closing your window if it's PuTTY or something else set to close on exit.
    [/list]

Sorry, but I'm a bit lost as to the purpose. Can you lay out a description of what you are trying to achieve?

Perhaps the logout should be before the EOF as a starter.
Should this really be an interactive script within the ssh bit?

If you can lay it out, then I'm sure we can help you.

Kind regards,
Robin

1 Like

Thanks for your response.. I have 500 odd servers which have some unused user directories , these directories need to be deleted.
I have one server which can be used to connect to all these servers via ssh wihout any password.
The idea is to put the entire server list is file and run a for loop and connect to all those servers do cd to the /home area .. then interactivily ask for the directory to be deleted. Once the input is provided it should delete the directory and then logout from that server to continue the loop for the remaining servers.

Hope I am able to explain what is required :slight_smile:

@rbatte1: if you replace the for loop with a while read loop, then this takes stdin away from ssh (like ssh was taking stdin away from the read statement from the remote execution script). So in addition to my suggestion in post #2 you need to read the server name from a different file descriptor:

while read server name  <&3        # File read at the done statement
do
  .....
done 3< /tmp/list
2 Likes

Thanks all for you suggestion.. I will make the necessary change and then try. Thanks a lot again !!

Hi ,

I created the final script as per your suggestion however, the script just runs and comes out of loop without asking any inputs:

:/home/kampatel=> ./working.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Hpux server-1 B.11.31 U ia64 2459719568 unlimited-user license
Enter the dir >
no such file
Pseudo-terminal will not be allocated because stdin is not a terminal.
HP-UX  Server-2 B.11.31 U ia64 2191140766 unlimited-user license
Enter the dir >
no such file

Script:
------

#!/bin/ksh
for i in `cat /tmp/list`
do
  ssh -n -t "$i" "$(
  cat << EOF
    uname -a
echo "Enter the dir >"
    read path
if [ -d "$path" ]
then
echo "removing $path as per the input .."
rm $path
else
echo "no such file"
fi
exit
EOF
  )"
done

If written in while loop it also does the same thing completes the loop without asking any input or deleting the files.

You are using the -n option, which means redirect stdin from /dev/null.

The while lopp script:

set -x
#!/bin/ksh
while read servername  <&3
do
ssh -t $servername
uname -a
cd /home
echo "Enter Dir to be removed >"
read Dir
if [ -d "$Dir" ]
then
echo "$Dir exists"
else
echo "$Dir is not thre"
fi
logout
done 3< /tmp/list

It falls in the shell of the remove server.. if I exist , then it prompts for the options:

riker:/home/kampatel=> ./new_test.sh
+ 3< /tmp/list
+ read servername
+ 0<& 3
+ ssh -t server-1


 

HP-UX server-1 B.11.31 ia64 2459719568
 Server model: ia64 hp server Integrity Virtual Machine




You have mail.
You are superuser !

server-1:/root=>
server-1:/root=> exit
logout
Connection to server-1 closed.
+ uname -a
HP-UX server B.11.31 U ia64 0077323328 unlimited-user license
+ cd /home
+ echo Enter Dir to be removed >
Enter Dir to be removed >
+ read Dir
/home/kampatel/test
+ [ -d /home/kampatel/test ]
+ echo /home/kampatel/test is not thre
/home/kampatel/test is not thre
+ logout
./new_test.sh[16]: logout:  not found.
+ read servername
+ 0<& 3
+ ssh -t server-2

---------- Post updated at 06:18 AM ---------- Previous update was at 05:55 AM ----------

The problem is the above script just looks at the local servers path after i define the directory detail instead of looking into the remote server shell.. The script get executed, although it connects to the remote server it matches the path in the local servers and fails to remove the directories.

With the last script this is missing, as indicated in post #2:

"$(
  cat << EOF
    uname -a
echo "Enter the dir >"
    read path
if [ -d "$path" ]
then
echo "removing $path as per the input .."
rm $path
else
echo "no such file"
fi
exit
EOF
  )"