1

I'm running a script like so:

const someString = "text@ip:ip,text@ip:,";
const arg2 = "5";
let result = await new Promise((resolve, reject) => {
        child.exec(`"/path/to/script.sh" "${someString}" "${arg2}"`,
        (error=child.ExecException, stdout=string, stderr=string) => {
            if (error) {
                isErr = true;
                reject(error);
            }else {
                resolve(stdout); 
            }
        });
    });

The script receives arg2 fine as $2. However, $1 shows a blank string. I've logged the string in my Node.js app and it is correct. Possibly something to do with special characters in the string?

The script need to be run asynchronously relative to the application and synchronously relative to it's parent function(which is the case in the code snippet above).

EDIT: Here is the original code that I can't get working. It is to dynamically generate an ansible inventory.

nodejs:

async function buildInventory(site){
    const agentNumber = site.agentData.agentNumber;
    let hostsByType = {};
    let hosts = "";
    if ( site.hosts.length > 0 ){
        site.hosts.forEach(host => {
            if (hostsByType.hasOwnProperty(`${host.type}`)) {
                hostsByType[`${host.type}`].push(`${host.ip}`);
            }else{
                hostsByType[`${host.type}`] = [ `${host.ip}` ];
            }
        });
    }
    if ( hostsByType != {} ){
        for (const key in hostsByType) { // create arg in format type@ip:,type@ip:ip:,
        if (Object.hasOwnProperty.call(hostsByType, key)) {
            hosts = hosts + `${key}@`;
            hostsByType[key].forEach(ip => {
                hosts = hosts + `${ip}:`;
            });
            hosts = hosts + ',';
        }
        console.log(hosts); // string logged is in expected format
    }
}
    if ( hosts = "" ){
        hosts = "na";
    }
    let isErr = false;
    let result = await new Promise((resolve, reject) => {
        child.exec(`"/usr/raindrop/app/ansible/mkinv" "${hosts}" "${agentNumber}"`,
        (error=child.ExecException, stdout=string, stderr=string) => {
            if (error) {
                isErr = true;
                reject(error);
            }else {
                resolve(stdout); 
            }
        });
    });
    if( !isErr ){
        result = result.split(/\r?\n/)[0];
        if ( result == "genskipped" ){
            logger.log('info', `Inventory generation skipped(no hosts)`);
            return true;
        }else if ( result == "gensuccess"){
            logger.log('info', `Inventory generated`);
            return true;
        }else {
            logger.log('warn', `Unknown response from inventory generation script`);
            console.log(result);
            return false;
        }
    }else{
        logger.log('error', `Inventory generation error: ${result}`);
        return false;
    }
}

bash script:

#!/bin/bash
mkdir -p /data/ansible/$2
cd /data/ansible/$2
while [[ $1 == "na" ]];do
    echo "genskip"
    exit 0;
done
touch inventory.yml
echo "all:" > inventory.yml
echo "  children:" >> inventory.yml
IFS=',' read -a hostsByType <<< "$1" # arg in format type@ip:,type@ip:ip:,
echo $1 >> /logs/ansible-debug.log
for val in "$hostsByType";do
    while [[ "$val" != "" ]];do
        IFS='@' read -a data <<< "$val"
        echo "    ${data[0]}:" >> inventory.yml
        IFS=':' read -a hosts <<< "${data[1]}"
        c=1
        for host in "$hosts";do
            while [[ "$host" != "" ]];do
              echo "      host${c}: $host"
              c=$(($c + 1))
              break;
            done
        done
      break;
    done
done
subnet=$(cat /data/vpn/rain.conf | grep 'ipv4=')
IFS='=' read -a arr <<< $subnet
subnet=${arr[1]}
agent_ip="${subnet}${2}"
echo "  vars:"  >> inventory.yml
echo "    ansible_port: 22" >> inventory.yml
echo "    ansible_user: sisadm" >> inventory.yml
echo "    private_key_file: /data/ssh/keys/$2" >> inventory.yml
echo "    ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ProxyCommand=\"ssh -o \'ForwardAgent yes\' agent@$agent_ip -p 11522 \'ssh-add /home/agent/.ssh/id_rsa && nc %h %p\'\"'" >> inventory.yml
echo "gensuccess"

EDIT2: /logs/ansible-debug.log shows a new line every time the script is run. The inventory.yml the script creates:

all:
  children:
  vars:
    ansible_port: 22
    ansible_user: sisadm
    private_key_file: /data/ssh/keys/2
    ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ProxyCommand="ssh -o \'ForwardAgent yes\' [email protected] -p 11522 \'ssh-add /home/agent/.ssh/id_rsa && nc %h %p\'"'
4
  • Can't reproduce with your example. Commented Jun 19, 2022 at 12:09
  • @robertklep Added full code snippets, thanks. Commented Jun 19, 2022 at 13:00
  • 2
    off-topic, but why not use nodejs to generate the inventory in yaml format instead of the shell script? Commented Jun 19, 2022 at 13:12
  • @criztovyl Sometimes my head is too deep in the project... This is a valid answer and I may just. However, I've been trying to avoid the use of filesystem in nodejs. Bash handling files is a much cleaner operation in my opinion. I'm also able to more easily audit the use of io of the application(slightly primitive approach maybe). Commented Jun 19, 2022 at 13:18

1 Answer 1

1

Your issue is here:

if ( hosts = "" ){
    hosts = "na";
}

Try this:

if ( hosts == "" ){
    hosts = "na";
}
Sign up to request clarification or add additional context in comments.

2 Comments

Oh wow. Many thanks to your keen eye! I presume this is expected behavior as there was no error thrown? The if condition runs if invalid, I was not aware.
The condition re-assigns the variable to "". The if ("") evaluates to false, thus not setting hosts="na". A good practice (that I don't observe, ... but it's a good habit to take ...), would be to use if ("" == hosts) instead. As here, forgetting an = would have thrown.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.