# Remote script execution on Pi

**URL:** <https://community.particle.io/t/remote-script-execution-on-pi/27692>\
**Category:** Raspberry Pi\
**Created:** [December 2, 2016, 7:20pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692 "2016-12-02T19:20:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jvanier](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/jvanier/32/5542_2.png) [@jvanier](https://community.particle.io/u/jvanier)\
**Post date:** [December 2, 2016, 7:20pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/1 "2016-12-02T19:20:14Z")

</div>

Starting now you can run program and scripts on your Raspberry Pi from the Particle firmware.

To execute a script or command and wait for it to finish do:

```auto
Process proc = Process::run("/home/pi/script.sh arg1 arg2");
proc.wait();

```

[The detailed documentation for Process control is here](https://docs.particle.io/reference/firmware/raspberry-pi/#process-control)

Here’s an example for publishing the CPU temperature to the cloud:

```auto
void loop() {
  // Measure the CPU temperature
  Process proc = Process::run("vcgencmd measure_temp");
  proc.wait();
  // The output is temp=43.5'C
  proc.out().find("=");
  float cpuTemp = proc.out().parseFloat();
  Particle.publish("cpu_temp", String(cpuTemp));
  delay(1000);
}

```

Feedback on the Process interface is welcome.

---

<div class="post-metadata">

**Author:** ![nrobinson2000](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nrobinson2000/32/15624_2.png) [@nrobinson2000](https://community.particle.io/u/nrobinson2000)\
**Post date:** [December 2, 2016, 8:48pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/2 "2016-12-02T20:48:24Z")

</div>

This is awesome.

Edit:  
The example above crashes after a little while, and when it does, particle-agent copies tinker over it, deleting the firmware.

```auto
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
  what(): resolve: Host not found (authoritative)
Firmware exited with status pid 829 SIGABRT (signal 6)
Quitting firmware gracefully
Entering safe mode because firmware exited too many times in a row. Reverting to Tinker

```

Update:  
I was able to fix this by increasing the delay.

---

<div class="post-metadata">

**Author:** ![gusgonnet](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/gusgonnet/32/27491_2.png) [@gusgonnet](https://community.particle.io/u/gusgonnet)\
**Post date:** [December 12, 2016, 1:49am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/3 "2016-12-12T01:49:46Z")

</div>

> [@nrobinson2000](#):
>
> Update:I was able to fix this by increasing the delay.

Hi, what delay did you increase? thanks!  
Gustavo.

---

<div class="post-metadata">

**Author:** ![nrobinson2000](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nrobinson2000/32/15624_2.png) [@nrobinson2000](https://community.particle.io/u/nrobinson2000)\
**Post date:** [December 12, 2016, 2:35am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/4 "2016-12-12T02:35:42Z")

</div>

The actual solution was found on this thread:

> [@\[SOLVED\] Firmware always reset to tinker on reboot](https://community.particle.io/t/solved-firmware-always-reset-to-tinker-on-reboot/27714):
>
> I have noticed that everytime I reboot my Pi, the firmware is reset to Tinker. Here is what I find in particle-agent logs: terminate called after throwing an instance of 'boost::exception\_detail::clone\_impl\<boost::exception\_detail::error\_info\_injector\<boost::system::system\_error\> \>' what(): resolve: Host not found (non-authoritative), try again later Firmware exited with status pid 879 SIGABRT (signal 6) Quitting firmware gracefully Entering safe mode because firmware exited too many times …

Basically whenever the Pi's connection to the particle cloud was broken, the firmware was reset by particle-agent.

This was fixed by the one and only @jvanier

> [@gusgonnet](#):
>
> Hi, what delay did you increase? thanks!

I changed `delay(1000);` to `delay(4000);`.

---

<div class="post-metadata">

**Author:** ![legoguy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/legoguy/32/7408_2.png) [@legoguy](https://community.particle.io/u/legoguy)\
**Post date:** [December 12, 2016, 5:38pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/5 "2016-12-12T17:38:06Z")

</div>

I ran a “whoami” command with this interface, and the processes run as `root`. This gives an overwhelmingly dangerous level of control to the firmware, and could allow for arbitrary code execution resulting in installation of compromising software if the firmware accepts user input by cloud functions or other mechanisms. This could open up poorly coded firmwares to something akin to the IoT botnets we saw wreaking havoc lately with DynDNS. Are there plans in the future to at least drop the firmware process to a less-privileged user? Running as an unprivileged user may be a hinderance, but it might be a good idea in the name of safety.

---

<div class="post-metadata">

**Author:** ![nrobinson2000](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nrobinson2000/32/15624_2.png) [@nrobinson2000](https://community.particle.io/u/nrobinson2000)\
**Post date:** [December 12, 2016, 6:45pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/6 "2016-12-12T18:45:50Z")

</div>

The Raspberry Pi GPIO and low-level processes can only be accessed by root, and it because of this why the firmware must run as root.

> [@legoguy](#):
>
> could allow for arbitrary code execution resulting in installation of compromising software if the firmware accepts user input by cloud functions or other mechanisms. This could open up poorly coded firmwares to something akin to the IoT botnets we saw wreaking havoc lately with DynDNS.

If your Particle account or access token is compromised then so are all of the devices linked to it. Particle is trying to make their platform as secure as possible to reduce these risks.

---

<div class="post-metadata">

**Author:** ![legoguy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/legoguy/32/7408_2.png) [@legoguy](https://community.particle.io/u/legoguy)\
**Post date:** [December 12, 2016, 7:02pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/7 "2016-12-12T19:02:59Z")

</div>

Regarding the need for low-level access; that’s fair enough.

However, I can think of many ways this could go awry without having a compromised account / token. The use of webhooks or TCPClient to pull data in from other servers, and then using the retrieved data within system calls / Process::run() could open up the opportunity for a compromised web service (outside of Particle’s control) to execute commands on a Pi.

Granted, the attacker would need to know a _lot_ of specific details to execute such a compromise… across multiple platforms and unique firmwares, but it’s still technically “possible”. Food for thought.

---

<div class="post-metadata">

**Author:** ![nrobinson2000](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nrobinson2000/32/15624_2.png) [@nrobinson2000](https://community.particle.io/u/nrobinson2000)\
**Post date:** [December 12, 2016, 7:13pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/8 "2016-12-12T19:13:52Z")

</div>

> [@legoguy](#):
>
> Granted, the attacker would need to know a lot of specific details to execute such a compromise... across multiple platforms and unique firmwares, but it's still technically "possible". Food for thought.

It is very possible. Say you are polling data from somewhere and one day `; rm -rf -no-preserve-root /` is attached to the response string and called inside of Process::run(). The firmware would happily go erase your entire SD card. There are even worse commands that could be run and it would just require `;` and then the command for them to be executed.

---

<div class="post-metadata">

**Author:** ![jvanier](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/jvanier/32/5542_2.png) [@jvanier](https://community.particle.io/u/jvanier)\
**Post date:** [December 13, 2016, 4:04pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/9 "2016-12-13T16:04:35Z")

</div>

> [@legoguy](#):
>
> I ran a "whoami" command with this interface, and the processes run as root.

As @nrobinson2000 mentioned, the GPIO access is done by direct memory writes to the GPIO registers which can only be done by `root`.

The `Process::run` can run commands as other users by doing `Process::run("sudo -u pi my_command");` This would prevent accidentally running commands that affect the system. This can be added to the docs, or this behavior could be the default, unless someone does `Process::run_sudo()` maybe. What do you think?

---

<div class="post-metadata">

**Author:** ![legoguy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/legoguy/32/7408_2.png) [@legoguy](https://community.particle.io/u/legoguy)\
**Post date:** [December 13, 2016, 4:30pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/10 "2016-12-13T16:30:13Z")

</div>

Would it be better to have two, or maybe three overrides for `Process::run()`?

The default (as it exists already) could be modified to run as a less privileged user via an implied `sudo -u ...` (maybe `nobody`, or even `pi`? Although some people might remove `pi` on their device… and `nobody` would severely limit the amount of functionality available)

```auto
Process::run("command");

```

The second override allows you to specify the name of the user you wish to run as by string:

```auto
Process::run("command", "root");

```

Optionally, the third override allows you to specify the UID of the user you wish to run as by number:

```auto
Process::run('command', 0);

```

**NOTE** : The problem with using `sudo` is that it breaks the usual STDIN/STDOUT/STDERR piping semantics. We would need to handle this silently, likely by running `sudo -u {{user}} sh -c '{{command}}'`, so that it doesn’t cause headaches for the users of this functionality. We’d also need to escape single quotes when necessary…

---

<div class="post-metadata">

**Author:** ![jvanier](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/jvanier/32/5542_2.png) [@jvanier](https://community.particle.io/u/jvanier)\
**Post date:** [December 13, 2016, 6:59pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/11 "2016-12-13T18:59:47Z")

</div>

`Process::run` already runs commands through `sh -c {{command}}` and the piping is already customized to be able to provide input / capture output. So I don’t expect issues with doing `sudo -u {{user}}` within `Process::run`.

---

<div class="post-metadata">

**Author:** ![nrobinson2000](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nrobinson2000/32/15624_2.png) [@nrobinson2000](https://community.particle.io/u/nrobinson2000)\
**Post date:** [December 13, 2016, 7:17pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/12 "2016-12-13T19:17:43Z")

</div>

I like the overrides you are suggesting, especially:

```auto
Process::run("command", "user");

```

I think this would be good notation for people that are less familiar with bash, and it wouldn’t require them to type `sudo -u`

---

<div class="post-metadata">

**Author:** ![legoguy](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/legoguy/32/7408_2.png) [@legoguy](https://community.particle.io/u/legoguy)\
**Post date:** [December 14, 2016, 6:17am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/13 "2016-12-14T06:17:37Z")

</div>

Of course, the ability to specify a user manually also opens up the ability to specify a non-existent user; I expect that sudo would probably be the one to break that news unless the firmware checks first. I guess it depends where the error should be handled.

---

<div class="post-metadata">

**Author:** ![ztynzo](https://avatars.discourse-cdn.com/v4/letter/z/ed8c4c/32.png) [@ztynzo](https://community.particle.io/u/ztynzo)\
**Post date:** [December 25, 2016, 4:09am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/14 "2016-12-25T04:09:06Z")

</div>

So while we’re talking about security…let’s think about if your [particle.io](http://particle.io) acount was compromised.

All of these talks about overrides for Process::run would be pointless as the attacker would be able to re-flash the firmware. (Not that there isn’t good discussion on the potential for using retrieved information to run in scripts…)

It might be nice to provide some information about how and why it might be a good idea to disable OTA updates with System.disableUpdates() – maybe even with some tutorial on how one could program in failsafes for enabling OTA updates.

I mean it’s all unlikely, but you still generally want to make yourself a harder target than the next guy right? So maybe a tool-tip type thing in the docs/code guide to reflect this would be helpful – don’t want to scare people, but also want them to be informed.

---

<div class="post-metadata">

**Author:** ![comperem](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@comperem](https://community.particle.io/u/comperem)\
**Post date:** [June 4, 2017, 1:49am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/16 "2017-06-04T01:49:59Z")

</div>

Hello,

This example code by @jvanier for `Process::run()` is great. It worked very well just a couple of weeks ago (early or mid May 2017) but now has stopped compiling for a Raspberry Pi target.

The example code clip at the very top of this post, copy-pasted generates this compiler error:

> ```
> processexample.ino:7:3: error: 'Process' was not declared in this scope
> Process proc = Process::run("vcgencmd measure_temp");
> ^
> processexample.ino:7:11: error: expected ';' before 'proc'
> Process proc = Process::run("vcgencmd measure_temp");
> ^
> processexample.ino:8:3: error: 'proc' was not declared in this scope
> proc.wait();
>    
> Error: Could not compile. Please review your code.
> 
> ```

The compiler error text is formatted nicely in the web IDE but otherwise it appears the Process #include header is no longer on the compiler line.

The complete raw compiler error is here:

> `Processing processexample.ino make -C ../newlib_nano make[1]: Entering directory '/firmware/newlib_nano' make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/firmware/newlib_nano' make -C ../user make[1]: Entering directory '/firmware/user' Building cpp file: processexample.cpp Invoking: ARM GCC CPP Compiler mkdir -p ../build/target/user/platform-0-lto arm-none-eabi-gcc -DSTM32_DEVICE -DSTM32F10X_MD -DPLATFORM_THREADING=0 -DPLATFORM_ID=0 -DPLATFORM_NAME=core -DUSBD_VID_SPARK=0x1D50 -DUSBD_PID_DFU=0x607F -DUSBD_PID_CDC=0x607D -DSPARK_PLATFORM -DFLASHEE_EEPROM -g3 -gdwarf-2 -Os -mcpu=cortex-m3 -mthumb -flto -DINCLUDE_PLATFORM=1 -DPRODUCT_ID=0 -DPRODUCT_FIRMWARE_VERSION=65535 -DUSE_STDPERIPH_DRIVER -DDFU_BUILD_ENABLE -DSYSTEM_VERSION_STRING=0.6.2 -DRELEASE_BUILD -I./inc -I../wiring/inc -I../system/inc -I../services/inc -I../communication/src -I../hal/inc -I../hal/shared -I../hal/src/core -I../hal/src/stm32 -I../platform/shared/inc -I../platform/MCU/STM32F1xx/STM32_StdPeriph_Driver/inc -I../platform/MCU/STM32F1xx/STM32_USB_Device_Driver/inc -I../platform/MCU/STM32F1xx/SPARK_Firmware_Driver/inc -I../platform/MCU/shared/STM32/inc -I../platform/MCU/STM32F1xx/CMSIS/Include -I../platform/MCU/STM32F1xx/CMSIS/Device/ST/Include -I../platform/NET/CC3000/CC3000_Host_Driver -I../dynalib/inc -I -I./libraries -I -I -I -I -I. -MD -MP -MF ../build/target/user/platform-0-ltoprocessexample.o.d -ffunction-sections -fdata-sections -Wall -Wno-switch -Wno-error=deprecated-declarations -fmessage-length=0 -fno-strict-aliasing -DSPARK=1 -DPARTICLE=1 -DSTART_DFU_FLASHER_SERIAL_SPEED=14400 -DSTART_YMODEM_FLASHER_SERIAL_SPEED=28800 -DSPARK_PLATFORM_NET=CC3000 -fno-builtin-malloc -fno-builtin-free -fno-builtin-realloc -DLOG_INCLUDE_SOURCE_INFO=1 -DPARTICLE_USER_MODULE -DUSE_THREADING=0 -DUSE_SPI=SPI -DUSE_CS=A2 -DUSE_SPI=SPI -DUSE_CS=A2 -DUSE_THREADING=0 -DMODULE_VERSION=0 -DMODULE_FUNCTION=3 -DMODULE_DEPENDENCY=0,0,0 -D_WINSOCK_H -D_GNU_SOURCE -DLOG_MODULE_CATEGORY="\"app\"" -fno-exceptions -fno-rtti -fcheck-new -std=gnu++11 -c -o ../build/target/user/platform-0-ltoprocessexample.o processexample.cpp processexample.ino: In function 'void loop()': processexample.ino:7:3: error: 'Process' was not declared in this scope Process proc = Process::run("vcgencmd measure_temp"); ^ processexample.ino:7:11: error: expected ';' before 'proc' Process proc = Process::run("vcgencmd measure_temp"); ^ processexample.ino:8:3: error: 'proc' was not declared in this scope proc.wait(); ^ ../build/module.mk:267: recipe for target '../build/target/user/platform-0-ltoprocessexample.o' failed make[1]: Leaving directory '/firmware/user'`

Is this example code clip still compiling on your end? Is there an include missing or is there a way to add it?

The web IDE is really cool but provides no way to grep the headers.

Marc

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [June 4, 2017, 4:07am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/17 "2017-06-04T04:07:50Z")

</div>

Yes, this still compiles, but your error output does suggest you are _not_ building for a RPi, but for Spark Core

> [@comperem](#):
>
> ```plaintext
> ./build/target/user/platform-0-ltoprocessexample.o processexample.cpp
> 
> ```

`platform-0` stands for Spark Core, RPi would be `platform-31`

Double check that you have selected Raspberry Pi as target in the Device drawer.

---

<div class="post-metadata">

**Author:** ![comperem](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@comperem](https://community.particle.io/u/comperem)\
**Post date:** [June 4, 2017, 11:22am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/18 "2017-06-04T11:22:48Z")

</div>

Hello @ScruffR,

Perfect. Your help solved this issue. It compiles just fine once the target device is selected. I recently added another device and had not figured out how to target one versus another.

With **no** device selected (i.e. no yellow star on the devices pane) the compiler defaults to spark, just as you pointed out.

By clicking the star on the left hand side of a device, it selects that device for compilation and targeting. That selection includes the target-specific libraries during compiling and linking. I didn’t know `platform-0` means spark and `platform-31` means Raspberry Pi. Good to know.

Image illustrating the selection:

 ![](https://us1.discourse-cdn.com/flex026/uploads/particle/original/2X/7/7f9196999fc6d9953c0129da59ed190363a4f929.JPG)

Thanks for the careful consideration and discovering this problem.

Marc

---

<div class="post-metadata">

**Author:** ![Flo](https://avatars.discourse-cdn.com/v4/letter/f/b38774/32.png) [@Flo](https://community.particle.io/u/Flo)\
**Post date:** [September 2, 2017, 7:12pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/19 "2017-09-02T19:12:50Z")

</div>

Hi everyone,

This is my first entry since I’m new to particle.  
Hope someone can answer.

I managed to execute commands either using the  
Process proc = Process::run(“command”);  
proc.wait();  
or the simple system(“command”)

This works fine with commands like shutdown now/restart now

Now I’m trying to open a browser window using the execution lines.  
Why doesn’t it work with e.g. xdg-open URL ?

Sorry if this is a rather stupid question,  
Best regards,  
Flo

---

<div class="post-metadata">

**Author:** ![nrobinson2000](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nrobinson2000/32/15624_2.png) [@nrobinson2000](https://community.particle.io/u/nrobinson2000)\
**Post date:** [September 2, 2017, 7:24pm UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/20 "2017-09-02T19:24:23Z")

</div>

I think you need to set the `DISPLAY` variable in bash.

Kind of like this:

> <https://askubuntu.com/questions/47642/how-to-start-a-gui-software-on-a-remote-linux-pc-via-ssh/47658#47658>

You could probably use

`Process::run("DISPLAY=:0 xdg-open ...")`

---

<div class="post-metadata">

**Author:** ![Flo](https://avatars.discourse-cdn.com/v4/letter/f/b38774/32.png) [@Flo](https://community.particle.io/u/Flo)\
**Post date:** [September 3, 2017, 10:32am UTC](https://community.particle.io/t/remote-script-execution-on-pi/27692/21 "2017-09-03T10:32:47Z")

</div>

> [@nrobinson2000](#):
>
> DISPLAY=:0 xdg-open

Thanks for the quick reply nrobinson!  
I tried and it doesn't work.  
Also running python scripts doesn't show any results.  
This might be a matter of my setup:

I run the Google Assistant SDK on my Raspi 3  
Then, in IFTTT I setup an applet the uses the GA (with one text ingredient) as trigger and publishes an event to Particle. In Particle the text ingredient determines which if function is to be exexuted back on my RasPi.

```
 if (strcmp(data,"off")==0) {
    // if GA text ingredient is "off"
    digitalWrite(led,LOW);
    digitalWrite(boardLed,LOW);
  }
  else if (strcmp(data,"on")==0) {
    // if GA text ingredient is "on"
    digitalWrite(led,HIGH);
    digitalWrite(boardLed,HIGH);
  }
  else if (strcmp(data,"open")==0) {
    // if GA text ingredient is "open"
    Process proc = Process::run("DISPLAY=:0 xdg-open http://google.de");
    proc.wait();
  }

```

Controlling the GPIOs works fine (on/off). "open" is also recognized correctly and IFTTT sends the right "answer". Just the run() functions only works for shutdown/restart so far.

It'd be awsome to be able to run any script and finally have the unltimate control what GA does for me.  
Any ideas?

Best regards,  
Flo

[Next page](https://community.particle.io/t/remote-script-execution-on-pi/27692.md?page=2)
