0

Been trying to learn some better scripting in bash. Normally I can pull data values to iterate into command strings, but this one is showing my ignorance on syntax.

#! /bin/bash
while IFS=',' read name_c1 ip_c2
do
echo "Name:" $name_c1
echo "file:" v1-$ip_c2.yaml
export file=v1-$ip_c2.yaml
# cat $file
/usr/bin/incus launch images:debian/12/cloud $name_c1 -p prod-mgt --config=cloud-init.network-config=$(cat $file)

done < <(tail -n +1 host-list)

When I just echo the variables they render fine, but when rendering them from the command string, something is off. If I simplify the command string to just "/usr/bin/incus launch images:debian/12/cloud $name_c1"

Here is the output I get:

Name: c1
file: v1-192.168.0.222.yaml
Error: yaml: unmarshal errors:
  line 1: cannot unmarshal !!str `c2,192....` into api.InstancePut

I know my syntax is off most likely, any clues to what I need to change to render those variables pulled from the host file?

Example of the host-list file for clarity:

c1,192.168.0.222
c2,192.168.0.221
c3,192.168.0.220
c4,192.168.0.219
c5,192.168.0.218
c6,192.168.0.217

Thank you

3
  • Run shellcheck on your script. It gives very helpful hints on possible problems. Commented Aug 9 at 8:27
  • btw, according to the incus documentation the syntax to read the config from a file is < filename. Commented Aug 9 at 8:32
  • The command that works from cli - incus launch images:debian/12/cloud c11 -p prod-mgt --config=cloud-init.network-config="$(cat v1-192.168.0.217.yaml)" However running: incus launch images:debian/12/cloud "$name_c1" -p prod-mgt --config=cloud-init.network-config="$(cat $file)" gives me: Error: yaml: unmarshal errors: line 1: cannot unmarshal !!str c2,192.... into api.InstancePut ran it through shellcheck and cleaned it up a bit.
    – dj423
    Commented Aug 9 at 11:50

2 Answers 2

3

Some things to try:

First, add some debugging options to the sheebang declaration:

#! bash -vx 

That will display each line as it executes, with the expanded variables.

Second, in more complex scripts, consider adding a "safe mode" flag:

SAFE = ""
# SAFE = "echo :: "  # Make this conditional on your favourite "debug" flag. 

Then add this before any command you execute.

${SAFE} /usr/bin/incus launch images:debian/12/cloud $name_c1 -p prod-mgt --config=cloud-init.network-config=$(cat $file)

That way, you can run and test the script-y bits without invoking all the "dangerous" bits.

Finally, if your intention is to loop through the lines in the host-file, I think your loop construct is a bit suspect.
Try something like this:

while IFS=',' read name_c1 ip_c2
do
   echo "Name:" $name_c1
   echo "file:" v1-$ip_c2.yaml
   
   . . . 
   
done < host-list 
1

Found out incus reads from stdin by default, so that was messing me up.

Slightly better version:

#! /bin/bash
while IFS=',' read -r name_c1 ip_c2
do
    file=v1-$ip_c2.yaml

    cat >> "$file" << EOF
network:
  version: 1
  config:
    - type: physical
      name: eth0
      subnets:
        - type: static
          address: $ip_c2/24
          gateway: 192.168.0.1
          dns_nameservers:
            - 192.168.50.50
            - 192.168.0.1
          dns_search:
            - example.com
EOF

incus launch images:debian/12/cloud "$name_c1" -p prod-mgt --config=cloud-init.network-config="$(cat $file)" < /dev/null
done <  host-list

rm v1-*
exit

Thanks for all the input!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .