4

I have a script that open up terminal and open up 5 tabs, execute a certain command, and go to a certain working directory.

#!/bin/sh

gnome-terminal --tab --title="Zookeeper" --profile Hold -e "sh -c '/home/kafka_2.11-0.8.2.2/bin/zookeeper-server-start.sh /home/kafka_2.11-0.8.2.2/config/zookeeper.properties'" --tab --title="Kafka" --profile Hold -e "sh -c 'sleep 5; /home/kafka_2.11-0.8.2.2/bin/kafka-server-start.sh /home/kafka_2.11-0.8.2.2/config/server.properties'" --tab --title="APP-Binaries" --profile Hold --working-directory="/home/app-binaries" --tab --title="APP-DB" --profile Hold --working-directory="/home/prod/db"

Having everything in one line is hard to maintain. How do I make it better so it is easy to read ?

I've tried

#!/bin/sh

Tab=""

Tab+=("--tab --title='Zookeeper' --profile Hold -e 'sh -c /home/kafka_2.11-0.8.2.2/bin/zookeeper-server-start.sh /home/kafka_2.11-0.8.2.2/config/zookeeper.properties'") Tab+=( "--tab --title='Kafka' --profile Hold -e 'sh -c 'sleep 5; /home/kafka_2.11-0.8.2.2/bin/kafka-server-start.sh /home/kafka_2.11-0.8.2.2/config/server.properties'") Tab+=(" --tab --title='APP-Binaries' --profile Hold --working-directory='/home/app-binaries'") Tab+=(" --tab --title='APP-DB' --profile Hold --working-directory='/home/prod/db'")

echo "${Tab[@]}"

gnome-terminal "${Tab[@]}"

exit 0

So far it is not working yet! I'm open to any suggestions that you guys may have for me. I'm just looking to learn and improve it.

AdminBee
  • 22,803
code-8
  • 442
  • 2
    initialize to an array Tab=() and when adding elements, don't quote the whole thing: Tab+=(--tab --title='SSC-DB' --profile Hold --working-directory='/home/benu/SSC-V2/ssc-db') – glenn jackman Feb 13 '16 at 16:28
  • With what you currently have with Tab you are basically calling like gnome-terminal "" "--tab --title blah" "--tab --title blahblah" which is definitely not what you want. Just quote as how you would quote it normally, like in @glennjackman's suggestion. Note that you don't need to explicitly do any array initialization unless you are working with set -u. (Your current one adds an empty string element though). – Mingye Wang Feb 13 '16 at 20:07
  • 2
    By the way, arrays are bash stuff, so use #!/bin/bash as your shebang. – Mingye Wang Feb 13 '16 at 20:07
  • 1
    I'm voting to close this question as off-topic because this belongs on [codereview.se]. – muru Feb 13 '16 at 23:04
  • 1
    @muru I disagree, code review is generally for functioning code. – jordanm Feb 14 '16 at 01:04
  • See How can we run a command stored in a variable? about how to store a command in an array. (In short: don't add spurious quotes.) – ilkkachu Nov 02 '21 at 10:58
  • just use "" to escape new line, and you can write multi-line commands. The only limit is your command line limit (usually it is not less then 4 kbytes, but you can configure it in your distributive). – Saboteur Nov 02 '21 at 11:44

3 Answers3

10

You can use \ to split long commands over multiple lines.

Example:

#!/bin/bash

echo "Hello World!"
echo \
"Hello World!"

running this script results in

$ ./test.sh 

Hello World!
Hello World!

In your case you can use something like

#!/bin/bash    

gnome-terminal \
--tab --title="Zookeeper" --profile Hold -e "sh -c '/home/benu/Downloads/kafka_2.11-0.8.2.2/bin/zookeeper-server-start.sh /home/benu/Downloads/kafka_2.11-0.8.2.2/config/zookeeper.properties'" \
--tab --title="Kafka" --profile Hold -e "sh -c 'sleep 5; /home/benu/Downloads/kafka_2.11-0.8.2.2/bin/kafka-server-start.sh /home/benu/Downloads/kafka_2.11-0.8.2.2/config/server.properties'" \
--tab --title="SSC" --profile Hold -e "sh -c 'sleep 15; cd ~/gitnewssc/benu-ssc-binaries; ./startSSC.sh'" --working-directory="/home/benu/gitnewssc/benu-ssc-binaries" \
--tab --title="SSC-Binaries" --profile Hold --working-directory="/home/benu/gitnewssc/benu-ssc-binaries" \
--tab --title="SSC-DB" --profile Hold --working-directory="/home/benu/SSC-V2/ssc-db"
Wayne_Yux
  • 304
  • Ohh. Wow. Thank you guys so much for your help and time. – code-8 Feb 13 '16 at 15:03
  • @code8888 : you can further make it easier to read & easier to update by having as the 2nd line of the script: Kdir="/home/benu/Downloads/kafka_2.11-0.8.2.2" and then replace every occurence of /home/benu/Downloads/kafka_2.11-0.8.2.2 with ${Kdir} . This $Kdir variable call will be replaced by its value everywhere the "outer englobing quotes" are doublequotes (so here, it will work fine). As an added bonus, putting everything that may change (you may update kafka's version, for exemple) in variables at the beginning of the script makes it easy to spot & change – Olivier Dulac Nov 02 '21 at 13:54
4

Try it with writing \. Then the shell ignores the next new line and you can write options in a new line.

mkdrive2
  • 662
0

You could make small edit to your original idea with arrays - use arrayName[number]="tab assignment" form . Here's for instance what I did in interactive terminal session to open new terminal window ( and all these steps could easily be turned into a script ).

$ array[0]=" --tab --title 'Tab1' -e vi"                       

$ array[1]=" --tab --title 'Tab1' -e byobu"                    

$ gnome-terminal ${array[@]}

Genn Jackman in the comment noticed properly that quoting may become an issue especially if you have several difficult commands like in your case. Thus you might want to consider splitting up the information for tab and the actual command it needs to run into two corresponding arrays, each array entry per tab. Notice that we want to use cmd[x] as one whole string, hence quoting it, while tabinfo[1] has to expand to several different options

You may want to consider also placing filenames into variables like VAR=/path/to/file and using $VAR to reference those inside commands instead of having lengthy commands.

#!/bin/bash

function main()
{
   local cmd[1]="sh -c 'df;free;bash'"
   local cmd[2]="sh -c 'lsblk;cat /etc/fstab;bash'"
   local tabinfo[1]="--tab 'TAB1' --profile CRT -e"
   local tabinfo[2]="--tab 'TAB2'"
   gnome-terminal  ${tabinfo[1]} "${cmd[1]}" ${tabinfo[2]} "${cmd[2]}"
}

main
  • No. Leaving the array variable unquoted leads to negative consequences. The argument to the -e option contains whitespace and requires careful quoting. – glenn jackman Feb 13 '16 at 21:06
  • @glennjackman explan what negative consequences please ? Also -e option can be enclosed into single quotes, just like done with --title part. In general , I'd just like to see an example of what you're trying to say – Sergiy Kolodyazhnyy Feb 13 '16 at 21:21
  • @glennjackman made an edit, let me know what you think – Sergiy Kolodyazhnyy Feb 13 '16 at 23:48
  • 1
    You're getting too complicated. Read http://mywiki.wooledge.org/BashFAQ/050 and http://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells – glenn jackman Feb 13 '16 at 23:58