# VMware Tools power-on script fails because Elive exports a Bash-specific PS4

**URL:** <https://forum.elivelinux.org/t/vmware-tools-power-on-script-fails-because-elive-exports-a-bash-specific-ps4/4541>\
**Category:** Installed\
**Created:** [September 18, 2026, 2:31am UTC](https://forum.elivelinux.org/t/vmware-tools-power-on-script-fails-because-elive-exports-a-bash-specific-ps4/4541 "2026-09-18T02:31:10Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![patrick.regnouf](https://forum.elivelinux.org/user_avatar/forum.elivelinux.org/patrick.regnouf/32/3508_2.png) [@patrick.regnouf](https://forum.elivelinux.org/u/patrick.regnouf)\
**Post date:** [September 18, 2026, 2:31am UTC](https://forum.elivelinux.org/t/vmware-tools-power-on-script-fails-because-elive-exports-a-bash-specific-ps4/4541/1 "2026-09-18T02:31:11Z")

</div>

# VMware Tools power-on script fails because Elive exports a Bash-specific PS4

I ran into an issue with **Elive running as a VMware Workstation guest using `open-vm-tools`**.

On every VM startup, VMware displayed the following warning:

> VMware Tools power-on script did not run successfully

`open-vm-tools.service` itself was running normally, so I investigated the VMware power scripts.

Executing:

```bash
/etc/vmware-tools/poweron-vm-default

```

resulted in many errors from:

```plaintext
/etc/vmware-tools/scripts/vmware/network

```

of the form:

```plaintext
Bad substitution

```

The VMware network script starts with:

```bash
#!/bin/sh -x

```

and on this Elive installation:

```bash
readlink -f /bin/sh

```

returns:

```plaintext
/usr/bin/dash

```

## Finding the cause

After tracing the script execution, I found that the problem originates in:

```plaintext
/usr/lib/elive-tools/functions

```

Elive sets and exports `PS4` using:

```bash
export PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '

```

There are active `PS4` assignments both in the general initialization section and inside `el_make_environment()`.

For example, `el_make_environment()` contains:

```bash
if [[-n "${SOURCE}"]] ; then
    export PS4='+ [$(basename ${SOURCE} 2>/dev/null ) ${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '
else
    export PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '
fi

```

The problem is not setting `PS4` itself. The problem is **exporting it**.

`${FUNCNAME[0]}` is Bash-specific syntax. Because `PS4` is exported, child processes inherit it.

VMware then executes its network script through `/bin/sh -x`, which on this Elive installation is `dash`.

With tracing enabled, `dash` attempts to expand the inherited `PS4`. It cannot interpret `${FUNCNAME[0]}`, so every traced command can generate:

```plaintext
Bad substitution

```

The exported value could be seen directly with:

```bash
export -p | grep PS4

```

which originally returned:

```plaintext
export PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '

```

## Confirming that `el_make_environment()` exports it

I isolated `el_make_environment()` and checked `PS4` before and after calling it.

Before:

```plaintext
typeset PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '
PS4 not exported

```

After:

```plaintext
export PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '

```

So `el_make_environment()` explicitly changes `PS4` from a shell-local variable into an exported environment variable.

I also traced the loading of `/usr/lib/elive-tools/functions`, which showed another active assignment of the same form in the general initialization code.

## Fix

I changed the active assignments in:

```plaintext
/usr/lib/elive-tools/functions

```

from:

```bash
export PS4='...'

```

to:

```bash
PS4='...'

```

For example:

```bash
PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '

```

and inside `el_make_environment()`:

```bash
if [[-n "${SOURCE}"]] ; then
    PS4='+ [$(basename ${SOURCE} 2>/dev/null ) ${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '
else
    PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '
fi

```

This keeps Elive's custom debugging `PS4` in the current shell, but prevents child processes from inheriting it.

After the change, a fresh interactive zsh reports:

```bash
typeset -p PS4

```

as:

```plaintext
typeset PS4='+ [${FUNCNAME[0]:+${FUNCNAME[0]}} ${LINENO}] '

```

while:

```bash
export -p | grep PS4

```

returns nothing.

In other words, the custom `PS4` still exists, but it is no longer exported.

## VMware test after the fix

I then tested the actual VMware power-on script again:

```bash
/etc/vmware-tools/poweron-vm-default
echo "VMware exit=$?"

```

It ran normally through the VMware `#!/bin/sh -x` network script.

There were **no `Bad substitution` errors** , and it completed with:

```plaintext
VMware exit=0

```

I then rebooted the VMware guest.

The reboot completed successfully and the original VMware warning:

> VMware Tools power-on script did not run successfully

**did not appear anymore.**

So this fixed the problem in my VMware installation.

## Upgrade-resistant workaround

Directly editing `/usr/lib/elive-tools/functions` is useful for proving the cause, but that file is package-managed and an Elive update could overwrite the modification.

A safer local workaround is therefore to leave the packaged Elive file unchanged and add the following to:

```plaintext
/root/.zshrc.local

```

```zsh
# Elive uses a Bash-specific PS4.
# Keep PS4 local to zsh so /bin/sh (dash) children do not inherit it.
typeset +x PS4

```

`/root/.zshrc` loads the Elive functions and calls `el_make_environment()` before sourcing `/root/.zshrc.local`.

Therefore this local setting removes the export attribute from `PS4` after Elive has initialized the shell.

Elive keeps its custom `PS4` value for zsh debugging, while child programs no longer inherit it.

This should also survive upgrades of the `elive-tools` package.

## Scope of the problem

I encountered and reproduced this specifically in an **Elive VMware guest using open-vm-tools**.

I have not observed the same visible problem on my bare-metal Elive installations.

However, I don't think the underlying issue is necessarily VMware-specific.

The underlying sequence is:

```plaintext
Elive zsh
    |
    +-- /usr/lib/elive-tools/functions
            |
            +-- exports Bash-specific PS4
                    |
                    +-- child process inherits PS4
                            |
                            +-- /bin/sh is dash
                                    |
                                    +-- script runs with -x
                                            |
                                            +-- dash expands PS4
                                                    |
                                                    +-- ${FUNCNAME[0]}
                                                            |
                                                            +-- Bad substitution

```

VMware exposes the problem because its `open-vm-tools` network script happens to use:

```bash
#!/bin/sh -x

```

but in principle another program could trigger the same issue if it launches a non-Bash `/bin/sh` with tracing enabled while inheriting this environment.

## Suggested upstream fix

Unless there is a specific reason why the Elive debugging prompt needs to propagate into child shells, I think the proper upstream solution would be to **stop exporting `PS4` from `/usr/lib/elive-tools/functions`**.

That is, use:

```bash
PS4='...'

```

instead of:

```bash
export PS4='...'

```

This preserves the useful Elive debugging prompt in the current shell while preventing Bash-specific `PS4` syntax from leaking into `dash` or other child shells.

For VMware/open-vm-tools, this completely resolved the issue in my testing.

---

<div class="post-metadata">

**Author:** ![Thanatermesis](https://forum.elivelinux.org/user_avatar/forum.elivelinux.org/thanatermesis/32/3_2.png) [@Thanatermesis](https://forum.elivelinux.org/u/Thanatermesis)\
**Post date:** [September 18, 2026, 11:19am UTC](https://forum.elivelinux.org/t/vmware-tools-power-on-script-fails-because-elive-exports-a-bash-specific-ps4/4541/2 "2026-09-18T11:19:51Z")

</div>

Ah, that's a nice catch,

BTW dash is the default shell in debian

I personally never liked dash because of its limitations, but is meant to be faster & lighter so that's why Elive keeps it as the default "sh" on the system.

> <https://github.com/Elive/elive-tools/commit/a3e24cb5f27800af966b84e5f9c9ff9c9a885034>

Fixed 🙂 , going to upload packages now...
