# State-scripts documentation: how to use them without Yocto

**URL:** <https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744>\
**Category:** General Discussions\
**Tags:** state-scripts\
**Created:** [June 24, 2019, 3:25pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744 "2019-06-24T15:25:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ster](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/ster/32/282_2.png) [@ster](https://hub.mender.io/u/ster)\
**Post date:** [June 24, 2019, 3:25pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/1 "2019-06-24T15:25:29Z")

</div>

The documentation doesn’t really help to understand how to implement and include state scripts.  
Question I have (and probably other newcomers will):

- ~~can state scripts be included in artifacts or they are a part of Mender client?~~ (covered in docs)
- ~~how to design them?~~ (covered in docs)
- where to place them/how to include in the created artifact/image?
- can they differ for different types of artifact/update-modules (e.g. rootfs vs single file) ?

Will be extremely thankful for any hints where to look at.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [June 24, 2019, 5:04pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/2 "2019-06-24T17:04:03Z")

</div>

Regarding storage location, see [https://docs.mender.io/2.0/artifacts/state-scripts#root-file-system-and-artifact-scripts](https://docs.mender.io/2.0/artifacts/state-scripts#root-file-system-and-artifact-scripts) for more details. Basically the “Root Filesystem” scripts go in /etc/Mender/scripts and the artifact scripts are added by the mender-artifact invocation. See ‘mender-artifact write module-image --help’ for more details.

The specifics for full-image versus partial updates can be found here: [https://github.com/mendersoftware/mender/blob/2.0.0/Documentation/update-modules-v3-file-api.md](https://github.com/mendersoftware/mender/blob/2.0.0/Documentation/update-modules-v3-file-api.md)

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [June 25, 2019, 6:30am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/3 "2019-06-25T06:30:43Z")

</div>

> [@ster](#):
>
> can they differ for different types of artifact/update-modules (e.g. rootfs vs single file)

This is an ambiguous question. No, they can’t, in the sense that they are update module agnostic, they don’t care (and in fact, cannot find out) which type of update is in progress. This is intentional, since in the future, multiple updates may be supported inside one artifact.

But on the other hand, yes they can, in the sense that you can include any script you want in the artifact, and if you make a new artifact, with a different update type, you can include a different state script.

---

<div class="post-metadata">

**Author:** ![ster](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/ster/32/282_2.png) [@ster](https://hub.mender.io/u/ster)\
**Post date:** [June 25, 2019, 7:18pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/4 "2019-06-25T19:18:15Z")

</div>

so no out-of-the-box way of adding state scripts to artifacts generated by `mender-convert` for now?

---

<div class="post-metadata">

**Author:** ![mirzak](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/mirzak/32/2056_2.png) [@mirzak](https://hub.mender.io/u/mirzak)\
**Post date:** [June 26, 2019, 7:02am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/5 "2019-06-26T07:02:48Z")

</div>

> so no out-of-the-box way of adding state scripts to artifacts generated by `mender-convert` for now?

Correct, you will need to create a new Mender Artifact using `mender-artifact` and the `ext4` image once the `mender-convert` process is completed.

---

<div class="post-metadata">

**Author:** ![ster](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/ster/32/282_2.png) [@ster](https://hub.mender.io/u/ster)\
**Post date:** [June 26, 2019, 1:06pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/6 "2019-06-26T13:06:21Z")

</div>

One more question:  
The naming of state scripts intended to be included in roofs is well documented.  
But the naming requirements for scripts coming inside artifacts are confusing.

From one side, docs say it should follow the following format, same as ‘normal’ state scripts:

```
<STATE_NAME>_<ACTION>_<ORDERING_NUMBER>_<OPTIONAL_DESCRIPTION>

```

From the other hand, [Mender Artifact file format](https://github.com/mendersoftware/mender-artifact/blob/master/Documentation/artifact-format-v3.md#version-3) spec shows example of state-scripts named as (using dots)

```
+---header.tar.gz (tar format)
  | |
  | +---header-info
  | |
  | +---scripts
  | | |
  | | +---State.Enter
  | | +---State.Leave
  | | +---State.Error
  | | `---<more scripts>

```

Another thing which is unclear (just a general case, not related to my use case) is whether `Artifact`-prefixed state scripts are **only** intended to be included in the artifacts or can be placed in rootfs (`/etc/mender/scripts`) as well?

* * *

My use case is simple and common: I need to copy saved wifi credentials (wpa\_supplicant.conf file in case of raspbian) from old rootfs to new one when full image updates are performed to not loose connectivity after reboot (considering symlinking to /data/ is not an option). I saw [retain-ssh-keys example](https://github.com/mendersoftware/mender/blob/master/examples/state-scripts/retain-ssh-keys/Download_Leave_01), but as I plan to perform not only full-image updates, but also single file updates without changing rootfs partition, I don’t need to perform this script before every artifact install. That’s why I think such script should be included in Artifacts with full-os updates only. Is it the right path to follow?

---

<div class="post-metadata">

**Author:** ![mirzak](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/mirzak/32/2056_2.png) [@mirzak](https://hub.mender.io/u/mirzak)\
**Post date:** [June 27, 2019, 9:04am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/7 "2019-06-27T09:04:31Z")

</div>

@kacf might have some input on the naming inconsistencies.

> Another thing which is unclear (just a general case, not related to my use case) is whether `Artifact` -prefixed state scripts are **only** intended to be included in the artifacts or can be placed in rootfs ( `/etc/mender/scripts` ) as well?

Artifact prefixed artifacts are **only** intended to be included in Artifacts and can not be placed in rootfs.

> That’s why I think such script should be included in Artifacts with full-os updates only. Is it the right path to follow?

Yes, this looks like a good path for me.

---

<div class="post-metadata">

**Author:** ![ster](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/ster/32/282_2.png) [@ster](https://hub.mender.io/u/ster)\
**Post date:** [June 27, 2019, 9:22am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/8 "2019-06-27T09:22:11Z")

</div>

Ok I will summarize info to potentially help others

> can state scripts be included in artifacts or they are a part of Mender client?

Both. Client-side state scripts (those for states which are not prefixed with `Artifact`) are executed by the mender client regardless of the contents or type of the artifact it installs.

State scripts for states perfixed with `Artifact` are intended to be only included in the Artifact itself, thus may vary between Artifacts.

> how to design them?

Some examples of client-side state scripts are in the [mender client repo](https://github.com/mendersoftware/mender/tree/master/examples/state-scripts). Artifact state scripts may follow the same logic and should follow the same naming format, i.e.  
`<STATE_NAME>_<ACTION>_<ORDERING_NUMBER>_<OPTIONAL_DESCRIPTION>`

`retain-ssh-keys` example may give an idea how to transfer files between old and new filesystems when performing full-rootfs updates, if storing persistent files in /data/ is not an option. Yet, IMHO this type of actions should rather be included in Artifact as `ArtifactInstall_Enter_...` script as such actions are only needed for full-os updates and not needed to be executed if you perform updates without swithing partitions (i.e. using update modules)

> where to place state scripts/how to include in the created artifact/image?

Client state scripts should be placed in `/etc/Mender/scripts` of the new rootfs. To add them to an SD image, you can use [Modifying disk images](https://docs.mender.io/2.0/artifacts/modifying-a-disk-image) workflow from the docs.

To add client state scripts to a Mender artifact, you can use `mender-artifact cp`. Keep in mind it is a slow process and takes ~5 min per one file on ~300 MB Artifacts.

In addition, there’s no way of adding Artifact state scripts to already created Mender artifacts with `mender-artifact`. Thus if you use `mender-convert` workflow and need to include both clien and artifact state scripts, you can discard .mender file generated by `mender-convert`, mount .ext4 and copy all required client state scripts inside (as well as your mender.config, identity and inventory if needed), and then create mender Artifact from .ext4 yourself using `mender-artifact write rootfs-image` adding all your Artifact scripts by using `--script`, something like

```
mender-artifact --compression "lzma" write rootfs-image \
   --file "$releaseName-mender.ext4" \
   --device-type "raspberrypi3" \
   --artifact-name "$releaseName-mender.mender" \
   --script "$scriptsDir/ArtifactInstall_Enter_01_retain_wpa_supplicant" \ 
   --script "$scriptsDir/another_script"  

```

To verify that the scripts are added to the Artifact, you can open .mender as a .tar and check the contents of /header.tar.gz/scripts/

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [July 3, 2019, 7:33am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/9 "2019-07-03T07:33:46Z")

</div>

> From one side, docs say it should follow the following format, same as ‘normal’ state scripts:
> 
> From the other hand, [Mender Artifact file format](https://github.com/mendersoftware/mender-artifact/blob/master/Documentation/artifact-format-v3.md#version-3) spec shows example of state-scripts named as (using dots)

Yeah, this is wrong/outdated. I have made some cleanups [here](https://github.com/mendersoftware/mender-artifact/pull/207).

---

<div class="post-metadata">

**Author:** ![dhoomakethu](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/dhoomakethu/32/630_2.png) [@dhoomakethu](https://hub.mender.io/u/dhoomakethu)\
**Post date:** [June 6, 2020, 2:37pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/10 "2020-06-06T14:37:31Z")

</div>

Can the state scripts be used along side `module-image` or do the states needs to be implement as part of the update module it self ?

My artifact looks like this but I don’t see the state script `ArtifactCommit_Leave` being triggered.

````auto
Mender artifact:
  Name: dummy_artifact_v1.0.0
  Format: mender
  Version: 3
  Signature: signed but no key for verification provided; please use `-k` option for providing verification key
  Compatible devices: '[armv7l]'
  Provides group:
  Depends on one of artifact(s): []
  Depends on one of group(s): []
  State scripts:
    ArtifactCommit_Leave_00

Updates:
    0:
    Type: custom-image
    Provides: Nothing
    Depends: Nothing
    Metadata: Nothing
    Files:
      name: artifact_info
      size: 36
      modified: 2020-06-06 17:10:17 +0530 IST
      checksum: 7f760b613d878a38cb1b4807a2aaef1b340efdcdc21454970d13c463cf8bb3f7
      name: dummy_artifact_v1.0.0.tar.gz
      size: 3072
      modified: 2020-06-06 17:10:17 +0530 IST
      checksum: 43e380153fe157ac9f5f45d7487bb182d571c8c47c225b3ef5284b14b0ef76f6```
````

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [June 8, 2020, 6:40am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/11 "2020-06-08T06:40:14Z")

</div>

State scripts should be triggered no matter whether you are using  
rootfs-image or module-image. Can you try a different type of state  
script, such as `ArtifactInstall_Enter` to see if that works?

---

<div class="post-metadata">

**Author:** ![sensslen](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/sensslen/32/245_2.png) [@sensslen](https://hub.mender.io/u/sensslen)\
**Post date:** [September 2, 2020, 11:14am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/12 "2020-09-02T11:14:33Z")

</div>

Do I understand this correctly?

If I need to add Artifact state scripts and I use mender-convert, I must discard the mender artifact created and add the state script using `mender-artifact [...] --script "path/to/my/script"`?

---

<div class="post-metadata">

**Author:** ![kacf](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/kacf/32/146_2.png) [@kacf](https://hub.mender.io/u/kacf)\
**Post date:** [September 2, 2020, 11:28am UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/13 "2020-09-02T11:28:16Z")

</div>

Best is to use an overlay. This page explains how to add state scripts when using mender-convert: [https://docs.mender.io/system-updates-debian-family/convert-a-mender-debian-image/state-scripts](https://docs.mender.io/system-updates-debian-family/convert-a-mender-debian-image/state-scripts)

---

<div class="post-metadata">

**Author:** ![sensslen](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/sensslen/32/245_2.png) [@sensslen](https://hub.mender.io/u/sensslen)\
**Post date:** [September 2, 2020, 1:05pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/14 "2020-09-02T13:05:43Z")

</div>

Thanks a lot for pointing me to the correct location.

---

<div class="post-metadata">

**Author:** ![sensslen](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/sensslen/32/245_2.png) [@sensslen](https://hub.mender.io/u/sensslen)\
**Post date:** [September 9, 2020, 2:05pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/15 "2020-09-09T14:05:59Z")

</div>

When following the guide you posted, I do get an error message stating:

```
	mender-artifact --compression gzip write rootfs-image --file work/rootfs.img --output-path deploy/2020-08-20-raspios-buster-armhf-lite-raspberrypi-cm3-mender.mender --artifact-name 0_0_0-ensiDebug --device-type raspberrypi-cm3 --state ArtifactStateScripts/ArtifactInstall_Leave_1_MigrateConfiguration.sh
	Incorrect Usage: flag provided but not defined: -state

```

I assume that this has to do with the file path I provide that contains the state script is somehow not accessible. Where should the state scripts be put in order for them to be accessible.

Note that I’m using docker-mender-convert

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [September 9, 2020, 3:24pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/16 "2020-09-09T15:24:18Z")

</div>

The command line option should be “–script” rather than “–state”. The files are just loaded with the pathname given so if it’s a relative path it should be relative to the directory you are in when you invoke mender-artifact.

Drew

---

<div class="post-metadata">

**Author:** ![sensslen](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/sensslen/32/245_2.png) [@sensslen](https://hub.mender.io/u/sensslen)\
**Post date:** [September 9, 2020, 3:27pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/17 "2020-09-09T15:27:03Z")

</div>

Outch, thanks for correction!

---

<div class="post-metadata">

**Author:** ![thesillywhat](https://avatars.discourse-cdn.com/v4/letter/t/57b2e6/32.png) [@thesillywhat](https://hub.mender.io/u/thesillywhat)\
**Post date:** [September 18, 2020, 4:48pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/18 "2020-09-18T16:48:56Z")

</div>

The more I read about this more complicate it sounds

So to give an example of what I am trying to achieve.

Recently I found out that I had provide a patch to systemd so that I could change timezone in read only root file system.  
So the fix was in two areas.

1. I had to update rootfs
2. Add necessary file in persistent data section

As shown below

> root@raspberrypi-cm3:/etc# ls -lrt | grep localtime  
> lrwxrwxrwx 1 root root 22 Aug 19 11:56 localtime → /data/system/localtime  
> root@raspberrypi-cm3:/etc#

So now I have to create that structure (/data/system/localtime) in persistent data location.

And to achieve point 2, I have to create a state script to do so (As shown below)

```
#!/bin/sh
#
# Retain provide configuration files for timedatectl
#

mkdir /data/system/
if [[$? -eq 0]] ; then
	echo "Universal" > /data/system/timezone
else
	exit 1
fi

ln -s /usr/share/zoneinfo/Universal /data/system/localtime

if [[$? -ne 0]]; then
	exit 1
fi  

```

Then I need to name that state script (example Download\_Leave\_02)  
So once I create the state script then I run this command

```auto
mender-artifact --compression "lzma" write rootfs-image \
   --file "$releaseName-mender.ext4" \
   --device-type "raspberrypi3" \
   --artifact-name "$releaseName-mender.mender" \
   --script "$scriptsDir/Download_Leave_02" \ 
   --script "$scriptsDir/another_script"

```

And then create a delta update and use that output to update my machine?

Other question I do have a .ext4 file but I don’t have an mender.ext4 file. Is the naming convention that important?

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [September 18, 2020, 9:08pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/19 "2020-09-18T21:08:35Z")

</div>

That sounds about right. The mender.ext4 file should be fine.

---

<div class="post-metadata">

**Author:** ![thesillywhat](https://avatars.discourse-cdn.com/v4/letter/t/57b2e6/32.png) [@thesillywhat](https://hub.mender.io/u/thesillywhat)\
**Post date:** [September 21, 2020, 10:12pm UTC](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744/20 "2020-09-21T22:12:51Z")

</div>

I did try that out. But I keep getting the below mentioned error

> error: transient error: error executing leave script for after-reboot state: error running leave state script(s) for ArtifactReboot\_Leave state: statescript: error executing ‘ArtifactReboot\_Leave\_02’: -1 : fork/exec /var/lib/mender/scripts/ArtifactReboot\_Leave\_02: no such file or directory

But I do see the file

```
root@raspberrypi-cm3:/var/lib/mender/scripts# ls
ArtifactReboot_Leave_02

```

This is the command that I am using to generate the mender artifact.

`mender-artifact --compression "lzma" write rootfs-image --file "$releaseName-mender.ext4" --device-type "raspberrypi-cm3" --artifact-name "$releaseName-mender.mender" --script "$scriptsDir/ArtifactReboot_Leave_02"`

What am I missing? Is my state ordering wrong?

[Next page](https://hub.mender.io/t/state-scripts-documentation-how-to-use-them-without-yocto/744.md?page=2)
