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 -