<p>Try piping your output to grep and then failing based off of the return code of grep:</p>

<pre><code>npm install 2&gt;&amp;1 | grep "Error: connect ETIMEDOUT"
</code></pre>

<p>Per the <a href="https://www.gnu.org/software/grep/manual/html_node/Exit-Status.html" rel="nofollow noreferrer">grep documentation</a>,</p>

<blockquote>
  <p>the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred.</p>
</blockquote>

<p>If needed, you can <a href="https://stackoverflow.com/questions/15073048/bash-not-inverting-the-exit-status-of-a-command">"not" the return code</a> or just invert the conditional so that:</p>

<pre><code>if [ "$?" -ne "0" ]; then
    echo "Packer failed!"
    exit 1
fi
</code></pre>

<p>becomes instead:</p>

<pre><code>if [ "$?" -ne "1" ]; then
    echo "Packer failed!"
    exit 1
fi
</code></pre>

CC BY-SA 3.0
2017-06-01T08:27:59.587Z
Agreed, that this is the straightforward approach. My concern is that this approach will not detect all kind of errors that could happen. For instance, in my second example it would not have been triggered.
Philipp Claßen
CC BY-SA 3.0
2017-06-01T17:09:35.660Z
To check for additional errors, try capturing to a variable first using [command substitution](http://tldp.org/LDP/abs/html/commandsub.html), then echo the result through grep as many times as you would like checking for as many errors as you would like in a manner similar to the above.
James Shewey
CC BY-SA 3.0
2017-05-31T21:03:09.283Z
2017-05-31T21:03:09.283Z
James Shewey
<p>With the current Github outage, I noticed a problem with my <a href="https://www.packer.io/" rel="noreferrer">packer</a> setup. In a nutshell, I have a packer setup where I call a shell script that looks like this:</p>

<pre><code>#!/bin/bash
set -e
...
npm install
...
</code></pre>

<p>I expected that if there is any error during <code>npm install</code>, the script should fail and packer should abort. What I found out is that the script continued, even though the output looks like this:</p>

<pre><code>amazon-ebs: + npm install
amazon-ebs: npm ERR! fetch failed http://github.com/component/emitter/archive/1.0.1.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 192.30.253.112:80
amazon-ebs: npm ERR! fetch failed https://github.com/LearnBoost/node-XMLHttpRequest/archive/0f36d0b5ebc03d85f860d42a64ae9791e1daa433.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: fetch failed with status code 502
amazon-ebs: npm ERR! fetch failed https://github.com/component/global/archive/v2.0.1.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 192.30.253.113:443
amazon-ebs: npm WARN deprecated node-uuid@1.4.8: Use uuid module instead
amazon-ebs:
amazon-ebs: &gt; ws@0.4.31 install /opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws
amazon-ebs: &gt; (node-gyp rebuild 2&gt; builderror.log) || (exit 0)
amazon-ebs:
amazon-ebs: make: Entering directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws/build'
amazon-ebs: CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
amazon-ebs: bufferutil.target.mk:96: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
amazon-ebs: make: Leaving directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws/build'
amazon-ebs:
amazon-ebs: &gt; ws@0.4.31 install /opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws
amazon-ebs: &gt; (node-gyp rebuild 2&gt; builderror.log) || (exit 0)
amazon-ebs:
amazon-ebs: make: Entering directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
amazon-ebs: CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
amazon-ebs: bufferutil.target.mk:96: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
amazon-ebs: make: Leaving directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
amazon-ebs: proxy-socks-server@1.0.0 /opt/socks-proxy
amazon-ebs: npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
amazon-ebs: npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
amazon-ebs: npm WARN proxy-socks-server@1.0.0 No repository field.
amazon-ebs: ├─┬ cluster@0.7.7
amazon-ebs: │ ├── log@1.4.0
...
amazon-ebs: └─┬ ipv6@3.1.1
amazon-ebs: ├── cli@0.4.5
amazon-ebs: └── sprintf@0.1.3
amazon-ebs:
...
(packer continues)
</code></pre>

<p>So, it seems that <code>npm</code> does not return an error code if there are timeouts. The result is that packer will not notice it and in the end, it will result in a potentially broken AMI.</p>

<p><strong>Is there some way to make <code>npm install</code> less risky?</strong></p>

<p>When in doubt, I would prefer that it breaks better too much than too little when there is a chance that the installation was not successful. Then you would at least see it and then you can react on it. Otherwise, in the worst case, you will end up deploying a broken AMI.</p>

<hr>

<p>To simulate the error handling, I also made a local experiment where I disabled my network connection and run <code>npm install</code>. It took some while, but eventually gave up. Still it continued silently and returned a non-error return code:</p>

<pre><code>npm install &amp;&amp; echo "SUCCESS"
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN proxy-socks-server@1.0.0 No description
npm WARN proxy-socks-server@1.0.0 No repository field.
SUCCESS
</code></pre>

<p>Here, I would rather see it fail when it is run in an automated environment.</p>

<packer><npm>
Force script to fail if "npm install" has network issues
Philipp Claßen
# Force script to fail if "npm install" has network issues

(Asked by: username_0 on 2017-05-31)

With the current Github outage, I noticed a problem with my packer setup. In a nutshell, I have a packer setup where I call a shell script that looks like this:
#!/bin/bash
set -e
...
npm install
...

I expected that if there is any error during npm install, the script should fail and packer should abort. What I found out is that the script continued, even though the output looks like this:
amazon-ebs: + npm install
amazon-ebs: npm ERR! fetch failed http://github.com/component/emitter/archive/1.0.1.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 192.30.253.112:80
amazon-ebs: npm ERR! fetch failed https://github.com/LearnBoost/node-XMLHttpRequest/archive/0f36d0b5ebc03d85f860d42a64ae9791e1daa433.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: fetch failed with status code 502
amazon-ebs: npm ERR! fetch failed https://github.com/component/global/archive/v2.0.1.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 192.30.253.113:443
amazon-ebs: npm WARN deprecated node-uuid@1.4.8: Use uuid module instead
amazon-ebs:
amazon-ebs: > ws@0.4.31 install /opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws
amazon-ebs: > (node-gyp rebuild 2> builderror.log) || (exit 0)
amazon-ebs:
amazon-ebs: make: Entering directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws/build'
amazon-ebs: CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
amazon-ebs: bufferutil.target.mk:96: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
amazon-ebs: make: Leaving directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws/build'
amazon-ebs:
amazon-ebs: > ws@0.4.31 install /opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws
amazon-ebs: > (node-gyp rebuild 2> builderror.log) || (exit 0)
amazon-ebs:
amazon-ebs: make: Entering directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
amazon-ebs: CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
amazon-ebs: bufferutil.target.mk:96: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
amazon-ebs: make: Leaving directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
amazon-ebs: proxy-socks-server@1.0.0 /opt/socks-proxy
amazon-ebs: npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
amazon-ebs: npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
amazon-ebs: npm WARN proxy-socks-server@1.0.0 No repository field.
amazon-ebs: ├─┬ cluster@0.7.7
amazon-ebs: │ ├── log@1.4.0
...
amazon-ebs: └─┬ ipv6@3.1.1
amazon-ebs: ├── cli@0.4.5
amazon-ebs: └── sprintf@0.1.3
amazon-ebs:
...
(packer continues)

So, it seems that npm does not return an error code if there are timeouts. The result is that packer will not notice it and in the end, it will result in a potentially broken AMI.
Is there some way to make npm install less risky?
When in doubt, I would prefer that it breaks better too much than too little when there is a chance that the installation was not successful. Then you would at least see it and then you can react on it. Otherwise, in the worst case, you will end up deploying a broken AMI.

To simulate the error handling, I also made a local experiment where I disabled my network connection and run npm install. It took some while, but eventually gave up. Still it continued silently and returned a non-error return code:
npm install && echo "SUCCESS"
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN proxy-socks-server@1.0.0 No description
npm WARN proxy-socks-server@1.0.0 No repository field.
SUCCESS

Here, I would rather see it fail when it is run in an automated environment.

**Tags:** packer, npm


---

## 1 answers

### Answer by username_1 on 2017-05-31. Score: 4

Try piping your output to grep and then failing based off of the return code of grep:
npm install 2>&1 | grep "Error: connect ETIMEDOUT"

Per the grep documentation,

the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred.

If needed, you can "not" the return code or just invert the conditional so that:
if [ "$?" -ne "0" ]; then
    echo "Packer failed!"
    exit 1
fi

becomes instead:
if [ "$?" -ne "1" ]; then
    echo "Packer failed!"
    exit 1
fi

> **Comments:**
> **username_0**: Agreed, that this is the straightforward approach. My concern is that this approach will not detect all kind of errors that could happen. For instance, in my second example it would not have been triggered.  
> **username_1**: To check for additional errors, try capturing to a variable first using [command substitution](http://tldp.org/LDP/abs/html/commandsub.html), then echo the result through grep as many times as you would like checking for as many errors as you would like in a manner similar to the above.  

---

