Home > other >  Bash script. What am I doing wrong?
Bash script. What am I doing wrong?

Time:08-18

What am I doing wrong? Trying to execute chmod o-w for multiple paths after ssh to one server. File 1.txt contains two columns; one with same server called SERVER_hostname and second with different paths. I want script to ssh to that specific server hostname, and then make myself root(either toor, sudo eksh) and then run the command 'chmod o-w ' to those different paths from second column.

#!/bin/bash

read -r -a server < 1.txt  
echo "${server[0]}"  
echo "ssh -oBatchMode=yes -q "$(echo "${server[0]}")"  '"$(cat 1.txt | awk '{print " sudo eksh ; \ chmod o-w  " $NF";"}')"'" | sh

./254.sh  
SERVER_hostname
awk: warning: escape sequence `\ ' treated as plain ` '  
chmod: changing permissions of ‘/etc/nginx-controller/agent.configurator.conf.default’: Operation not permitted  
chmod: changing permissions of ‘/etc/nginx-controller/agent.controller.conf.default’: Operation not permitted    
chmod: changing permissions of ‘/etc/nginx-controller/copyright’: Operation not permitted  
chmod: missing operand after ‘o-w’
Try 'chmod --help' for more information.

1.txt

SERVER_hostname /etc/nginx-controller/agent.configurator.conf.default  
SERVER_hostname /etc/nginx-controller/agent.controller.conf.default  
SERVER_hostname /etc/nginx-controller/copyright   

Thank you.

CodePudding user response:

There are various ways of achieving this. But all have some tricks up their sleeve due to the usage of ssh. When using ssh in loops or complex constructs, you always have to be aware that ssh will slurp your /dev/stdin

The quickest way to implement would be to do multiple calls to ssh using a while-loop to read the file (See BashFAQ#001). However, we force ssh to use /dev/null as input stream. This way we avoid that the while loop is broken:

while read -r host file; do
  [ "$host" ] || continue
  [ "$file" ] || continue
  </dev/null ssh -oBatchMode=yes -q "${host}" -- sudo eksh -c "chmod o-w -- ${file}"
done < file.txt

The above method will perform multiple calls to ssh and might not be the most efficient way of doing things. You could build up the command using an array to contain the command arguments (See BashFAQ#050). In the case of the OP, this would be the different filenames:

file_list=()
while read -r h f; do [ "$f" ] && file_list =( "${f}" ); [ "$h" ] && host="$h"; done < file.txt
ssh -oBatchMode=yes -q "${host}" -- sudo eksh -c "chmod o-w -- ${file_list[@]}"

But again, there is an issue here if your argument list is too long. So the trick is now to use xargs directly over ssh. You could do something like this:

file_list=()
while read -r h f; do [ "$f" ] && file_list =( "${f}" ); [ "$h" ] && host="$h"; done < file.txt
printf "%s\n" "${file_list[@]}" | ssh "$host" "cat - | sudo eksh -c 'xargs chmod o-w --'"

Note: for some reason the command ssh "$host" sudo eksh -c 'xargs chmod o-w --' does not work. That is why we introduce the cat -

  • Related