0

I am trying to run a shell script on a Google Cloud Function.

I am using Node as the framework, and have tried different ways to run the script: execSync, execFileSync, spawnSync, etc:

module.exports.main = function() {
    try {
        const output = require('child_process').execSync(__dirname + '/run.sh', [], 
        {
            stdio: 'inherit',
            shell: '/bin/bash'
        });
    }
    catch (error) {
        process.exit(error.status);
    }
}

The behavior I get is very erratic. Overall I think it worked once, but the rest of the time I either get a connection error and nothing happens, or the function terminates "successfully", but nothing from the shell script gets outputted, so I don't know whether it even ran or not.

To be more precise, the log lines I see when the function "fails" are only the following:

Function execution started

Function execution took 122 ms, finished with status: 'connection error'

I couldn't detect a pattern in when it fails and when it runs.

Exact reproduction steps:

  • Create a Google Cloud Function
  • set its runtime to Node 8
  • set its trigger to Pub/Sub topic
  • set its function to call to main
  • create a zip containing
    • index.js with the content above (module.exports.main = ...)
    • run.sh containing only
      • #! /bin/bash
      • echo "hi"
  • upload zip as source for Cloud Function
  • go to Testing tab of Cloud function and hit "Test this functions"
  • view logs
Vic Seedoubleyew
  • 9,888
  • 6
  • 55
  • 76
  • 1) The code you shared is not a Cloud Function, but merely a Node.js script. If this code reproduces the problem with a local `Node.js` version, the problem is not related to Cloud Functions. If Cloud Functions is needed to reproduce the problem, please make sure that the *complete* relevant code is in your question. 2) If there is an error, include the exact error message and stack trace in your question. 3) Your code doesn't print the output from the shell script. – Frank van Puffelen Mar 14 '19 at 13:08
  • @FrankvanPuffelen Thanks for your swift reply. I appreciate your taking the time to look into this. I will answer your points in 3 different comments for easier reference – Vic Seedoubleyew Mar 14 '19 at 14:44
  • 1) a) The code I shared is the whole body of the function. I have added the function's signature to my post, but I don't think it will be of much help. – Vic Seedoubleyew Mar 14 '19 at 14:46
  • 1) b) When I run it locally I have no problem, it executes perfectly – Vic Seedoubleyew Mar 14 '19 at 14:46
  • 2) Unfortunately this is the problem: there is no stack trace whatsoever. The only log lines I see when it fails are `Function execution started` followed by `Function execution took 122 ms, finished with status: 'connection error'`. And when it doesn't fail, there is no error message or stack trace, just the absence of any output from shell script. – Vic Seedoubleyew Mar 14 '19 at 14:50
  • 3) I was under the impression that having `stdio: 'inherit'` as an option forwards the output back to the parent process output streams: https://stackoverflow.com/a/31104898/2873507 In any case, when I run it locally it does output the shell script's output to the console – Vic Seedoubleyew Mar 14 '19 at 14:51
  • It's really hard to say what's going on without seeing your entire deployment. We don't know 1) what kind of function this is or how you are triggering it 2) if run.sh is in the right place 3) what you expect run.sh to actually do. – Doug Stevenson Mar 14 '19 at 15:45
  • @DougStevenson Thanks for the reply! I agree that this is hard, this is why I have been banging my head as well! I'll answer your questions one by one – Vic Seedoubleyew Mar 14 '19 at 17:17
  • Doug 1) It is triggered by a pub/sub topic, but I get the error even when testing it manually, by hitting the "test the function" button – Vic Seedoubleyew Mar 14 '19 at 17:19
  • Doug 2) I think it is given that locally it runs fine – Vic Seedoubleyew Mar 14 '19 at 17:19
  • Doug 3) in order to debug I have made `run.sh` do nothing else than just echo a constant string – Vic Seedoubleyew Mar 14 '19 at 17:19
  • You should post exact reproduction steps in the question so that anyone can do this and see for themselves. There is really just not enough context. – Doug Stevenson Mar 14 '19 at 17:37
  • @DougStevenson Thanks for the reply! I have added exact reproduction steps to the post – Vic Seedoubleyew Mar 15 '19 at 16:34
  • Maybe run.sh does not end up having its executable permission set? Just execute bash directly against that script. – Doug Stevenson Mar 15 '19 at 16:36
  • @DougStevenson Thanks for the reply! I am not sure I understand what you suggest. If you suggest trying to run `./run.sh` locally, of course I have tried, and it works fine. Otherwise I am not sure how you suggest I run it against bash directly? – Vic Seedoubleyew Mar 15 '19 at 20:09
  • Execute `bash` and pass it the path of your script. `bash ./run.sh` - it's effectively the same thing. – Doug Stevenson Mar 15 '19 at 20:21
  • Yeah so that's what I did locally without a problem – Vic Seedoubleyew Mar 15 '19 at 22:33

1 Answers1

0

The solution I found was to switch to IBM Cloud Functions. They enable you to run a docker image, thus executing any binary is possible.

My suspicion as to why Google Cloud Function failed though, is that it probably ran out of memory. But that is just a guess

Vic Seedoubleyew
  • 9,888
  • 6
  • 55
  • 76