0

I am pulling my hair out,

#!/bin/sh
queryNumber=10

if [ "$1" == "start" ]; then
        systemctl start myProcess@{1..$queryNumber}
elif [ "$1" == "stop" ]; then
        systemctl stop myProcess@*
fi


Does anybody knows why I am not being able to pass the $queryNumber parameter onto the shell script

Gonzalo
  • 353
  • 2
  • 16
  • What command do you want to be executed? `systemctl start myProcess@1 2 3 4 5 6 7 8 9` or `systemctl start myProcess@1 myProcess@2...` – Mathieu Mar 03 '22 at 15:03
  • What I would like is to start a N amount of processes based on a variable @Mathieu but it seems like it enters on a confusion when I execute the script, it seems like bash can't read properly the ``$queryNumber`` variable – Gonzalo Mar 03 '22 at 15:03
  • 3
    Brace expansion occurs *before* parameter expansion, so this is a well known "can't do that" in `bash`. Use a loop to define an array instead. – chepner Mar 03 '22 at 15:06
  • BTW, if you want compatibility with `sh`, use `=` not `==` in your `[` commands. See [the POSIX specification for `test`](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html) for the list of guaranteed portable operators. – Charles Duffy Mar 03 '22 at 15:07
  • 2
    `echo {1..$queryNumber}` correctly writes `{1..10}`; the problem is not that bash can't "pass the variable into curly braces", the problem is that brace expansion does not work the way you think it does. – William Pursell Mar 03 '22 at 15:08
  • (Or, just call `systemctl start` multiple times in a loop, if you want to keep POSIX compatibility instead of using `bash`.) – chepner Mar 03 '22 at 15:08
  • One could overwrite `$@` (optionally inside a function) to do this while keeping POSIX compatibility and calling `systemctl start` only once. – Charles Duffy Mar 03 '22 at 15:09
  • 1
    Note that although "eval is evil", you may simply want `eval "systemctl ... {1..$queryNumber}"` – William Pursell Mar 03 '22 at 15:09
  • @CharlesDuffy Excellent suggestion. And timely enough that I could still edit the comment. – William Pursell Mar 03 '22 at 15:13
  • To demonstrate the overwrite-`$@` approach briefly: `set --; for ((i=0; i – Charles Duffy Mar 03 '22 at 15:16
  • 1
    Also, you should quote `myProcess@*`, as in, `systemctl stop 'myProcess@*'` -- otherwise it won't work if you run it in a directory that has a `myProcess@.service` file, or any other filename that starts with `myProcess@`. – Charles Duffy Mar 03 '22 at 15:20
  • Hi @CharlesDuffy many thanks for the answers, could you please, link me any helpful advanced book for learning bash and posix? Thanks. – Gonzalo Mar 03 '22 at 15:26
  • 1
    I recommend the Wooledge [BashGuide](https://mywiki.wooledge.org/BashGuide). The same wiki it's hosted on has several other useful resources -- among them, the [BashFAQ](https://mywiki.wooledge.org/BashFAQ) and the [BashPitfalls](https://mywiki.wooledge.org/BashPitfalls) page. Also good is the [bash-hackers' wiki](https://wiki.bash-hackers.org/). I strongly recommend you _avoid_ the ABS ("Advanced" Bash Scripting guide) and anything else from TLDP. – Charles Duffy Mar 03 '22 at 16:37
  • Incidentally, the resource I checked to find the POSIX-compliant equivalent to `for var in ((expr1; expr2; expr3))` was [the database for `greybot`](https://wooledge.org/~greybot/meta/), the #bash IRC channel factoid bot (that particular hint is in that database under the name "counting"). Lurking in that IRC channel over the course of some years in the early 2000s is how I personally learned bash. – Charles Duffy Mar 03 '22 at 16:43

1 Answers1

-2

This may be due to queryNumber is defined as Environment Variable or try running the program in Bash Shell rather than sh

  • 1
    This doesn't work even when the shell is known to be bash. It's [BashPitfalls #33](https://mywiki.wooledge.org/BashPitfalls#for_i_in_.7B1...24n.7D). – Charles Duffy Mar 03 '22 at 15:05
  • (also, `queryNumber` is in the OP's example a regular shell variable, _not_ an environment variable -- but since all environment variables named with valid shell variable names automatically have shell variables created for them, it would be the same either way). – Charles Duffy Mar 03 '22 at 15:14