0

So I have this script below to ssh to different server and change the ulimit from one value to another.

for host in $(</tmp/server_list.txt); do
ssh $host 'hostname -s; sudo sed -i.20180206 's/20480/40960/g'' /etc/security/limits.conf 
done

problem is since we have multiple single quotes starting and ending the script isn't working

could someone help modify or suggest some alternative that we can use instead of single quotes?

001
  • 13,291
  • 5
  • 35
  • 66
  • for host in $( – Sulata Kumari Feb 08 '18 at 15:17
  • Possible duplicate of [How to escape single quotes within single quoted strings?](https://stackoverflow.com/questions/1250079/how-to-escape-single-quotes-within-single-quoted-strings) – Benjamin W. Feb 08 '18 at 15:22
  • @BenjaminW. For this case there are better solutions than just escaping. See my answer. – migu Feb 08 '18 at 15:27
  • @migu Agree - there are many questions which would qualify as duplicates, I just picked one. – Benjamin W. Feb 08 '18 at 15:39
  • You can use double quotes in place of one of the sets of single quotes. Doesn't matter which one here. – glenn jackman Feb 08 '18 at 15:43
  • @BenjaminW. The other answer shows that this is specific to ssh. You didn't pick one of the possible duplicates. However, this questions probably belongs to unix.stackexchange.com or serverfault.com. – migu Feb 08 '18 at 15:44
  • @migu If you quote the string such that the single quotes are embedded properly, the duplicate answer definitely works as a solution in this case. Nothing ssh specific about it. – Benjamin W. Feb 08 '18 at 15:48
  • @BenjaminW. Read the second code snippet in https://stackoverflow.com/a/48689082/41362 It shows that you can pass multiple commands to ssh, which has nothing to do with quoting at all. – migu Feb 08 '18 at 15:50
  • @migu If you look closely, you'll see that the `;` had to be escaped to prevent the shell from interpreting it. This is quoting. If you disagree with my duplicate, just don't vote to close. – Benjamin W. Feb 08 '18 at 15:52

2 Answers2

0

It's possible to send a command to ssh through a pipe.

One way to do it is:

echo "commands" | ssh user@host

In your case you can write:

for host in $(</tmp/server_list.txt); do
  echo "hostname -s; sudo sed -i.20180206 's/20480/40960/g' /etc/security/limits.conf" \
      | ssh $host
done

A better way of reading lines from files is to use Bash's builtin command read. Combining this with passing multiple arguments to ssh, it looks like this:

while read host; do
    ssh $host hostname -s; sudo sed -i.20180206 s/20480/40960/g /etc/security/limits.conf
done < /tmp/server_list.txt

This is much simpler.

migu
  • 1,371
  • 1
  • 14
  • 23
  • 1
    You shouldn't loop over the input file like this, see https://mywiki.wooledge.org/DontReadLinesWithFor – Benjamin W. Feb 08 '18 at 15:40
  • @BenjaminW. This code is directly from the question. Please stop trolling me. – migu Feb 08 '18 at 15:45
  • I'm not trolling you. There is nothing preventing you from improving aspects in the code from the question that isn't directly related to the question itself, and looping over a file with `for` is not good practice. – Benjamin W. Feb 08 '18 at 15:49
  • @BenjaminW. I thought you were trolling me because you omitted the other answer which uses the same loop. Too much attention for me. ;) But of course you're right about the looping. – migu Feb 08 '18 at 15:52
  • 1
    Oh, I wasn't trying to "come after you". I'll mention it there as well. – Benjamin W. Feb 08 '18 at 15:53
  • Now my answer contains the improved way of reading lines from a file. – migu Feb 11 '18 at 14:19
0

Simple quotes around s/20480/40960/g are not necessary since it does not contains special characters. In add, for readability, I suggest to place whole command you want to execute inside a single argument to ssh (including /etc/security/limits.conf):

for host in $(</tmp/server_list.txt); do
    ssh $host "hostname -s; sudo sed -i.20180206 s/20480/40960/g /etc/security/limits.conf"
done

or in contrary, pass every argument in its own ssh argument:

for host in $(</tmp/server_list.txt); do
    ssh $host hostname -s \; sudo sed -i.20180206 s/20480/40960/g /etc/security/limits.conf
done
Jérôme Pouiller
  • 9,249
  • 5
  • 39
  • 47
  • You shouldn't loop over a file with `for`, use `while read` instead: https://mywiki.wooledge.org/BashFAQ/001 – Benjamin W. Feb 08 '18 at 15:53
  • @BenjaminW. It's true, `while read` is the best way to read a file line by line. However in case of this question, `$host` does not contains any spaces (nor tabs) and I find `while read` syntax more difficult to manipulate (probably matter of taste). – Jérôme Pouiller Feb 09 '18 at 10:05