[RFC 1/1] kas-container: rewrite container paths on-the-fly to host

2 views
Skip to first unread message

Felix Moessbauer

unread,
May 7, 2026, 6:02:48 AM (3 days ago) May 7
to kas-...@googlegroups.com, jan.k...@siemens.com, Felix Moessbauer
When running kas / bitbake inside the container, the printed paths point
into the container instead of the host. While this is technically
correct, it makes debugging harder as the user manually has to map these
back to the ones on the host (e.g. on build errors).

We now add the option --rewrite. When enabled, the output of the scripts
inside the container is captured and all mapped paths are rewritten. We
do not globally enable it, as capturing the output interfers with TTYs
(like kas shell, kas menu, oe menuconfig).

Signed-off-by: Felix Moessbauer <felix.mo...@siemens.com>
---
kas-container | 65 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/kas-container b/kas-container
index a9311e462..cb33ed321 100755
--- a/kas-container
+++ b/kas-container
@@ -85,6 +85,8 @@ usage()
"container.\n"
printf "%b" "--git-credential-store\tFile path to the git credential " \
"store\n"
+ printf "%b" "--rewrite\t\tRewrite container paths to host paths in output\n" \
+ "\t\t\t(may break interactive TTYs inside the container).\n"
printf "%b" "--no-proxy-from-env\tDo not inherit proxy settings from " \
"environment.\n"
printf "%b" "--repo-ro\t\tMount current repository read-only\n" \
@@ -256,8 +258,10 @@ forward_dir()
[ -z "$_varval" ] && return
FW_DIR_REL=$(realpath -q --relative-base="${KAS_WORK_DIR}" "$_varval")
if [ "${FW_DIR_REL}" = "$_varval" ]; then
+ register_path_rewrite "$_varval" "$2"
KAS_RUNTIME_ARGS="${KAS_RUNTIME_ARGS} -v ${FW_DIR_REL}:$2:$3 -e $1=$2"
else
+ register_path_rewrite "$_varval" "/work/${FW_DIR_REL}"
KAS_RUNTIME_ARGS="${KAS_RUNTIME_ARGS} -e $1=/work/${FW_DIR_REL}"
fi
}
@@ -284,14 +288,60 @@ enable_docker_rootless()
}

KAS_GIT_OVERLAY_FILE=""
+KAS_OUTPUT_FILTER_DIR=""
+KAS_OUTPUT_FILTER_PIDS=""
+KAS_OUTPUT_FILTER_RULES=""
kas_container_cleanup()
{
+ if [ -n "${KAS_OUTPUT_FILTER_PIDS}" ]; then
+ # shellcheck disable=SC2086
+ kill ${KAS_OUTPUT_FILTER_PIDS} 2>/dev/null || true
+ fi
+ if [ -n "${KAS_OUTPUT_FILTER_DIR}" ]; then
+ rm -rf "${KAS_OUTPUT_FILTER_DIR}"
+ fi
if [ -f "${KAS_GIT_OVERLAY_FILE}" ]; then
trace rm -f "${KAS_GIT_OVERLAY_FILE}"
fi
}
trap kas_container_cleanup EXIT INT TERM

+register_path_rewrite()
+{
+ _esc_from=$(printf '%s\n' "$2" | sed 's/[\\&|]/\\&/g')
+ _esc_to=$(printf '%s\n' "$1" | sed 's/[\\&|]/\\&/g')
+ KAS_OUTPUT_FILTER_RULES="${KAS_OUTPUT_FILTER_RULES}
+s|${_esc_from}|${_esc_to}|g"
+}
+
+run_with_host_path_rewrite()
+{
+ KAS_OUTPUT_FILTER_DIR=$(mktemp -d)
+ _RULES="${KAS_OUTPUT_FILTER_DIR}/rewrite.sed"
+ _STDOUT_FIFO="${KAS_OUTPUT_FILTER_DIR}/stdout"
+ _STDERR_FIFO="${KAS_OUTPUT_FILTER_DIR}/stderr"
+
+ printf '%s\n' "${KAS_OUTPUT_FILTER_RULES}" | sed '/^$/d' > "${_RULES}"
+ mkfifo "${_STDOUT_FIFO}" "${_STDERR_FIFO}"
+
+ sed -u -f "${_RULES}" < "${_STDOUT_FIFO}" &
+ _STDOUT_PID=$!
+ sed -u -f "${_RULES}" < "${_STDERR_FIFO}" >&2 &
+ _STDERR_PID=$!
+ KAS_OUTPUT_FILTER_PIDS="${_STDOUT_PID} ${_STDERR_PID}"
+
+ _RET=0
+ # shellcheck disable=SC2086
+ trace ${KAS_CONTAINER_COMMAND} run "$@" \
+ > "${_STDOUT_FIFO}" 2> "${_STDERR_FIFO}" || _RET=$?
+
+ wait "${_STDOUT_PID}" || true
+ wait "${_STDERR_PID}" || true
+ KAS_OUTPUT_FILTER_PIDS=""
+
+ return "${_RET}"
+}
+
set_container_image_var()
{
# if the image is explicitly set, use that
@@ -410,6 +460,10 @@ while [ $# -gt 0 ]; do
KAS_GIT_CREDENTIAL_STORE="$2"
shift 2
;;
+ --rewrite)
+ KAS_REWRITE=1
+ shift 1
+ ;;
--no-proxy-from-env)
KAS_NO_PROXY_FROM_ENV=1
shift 1
@@ -622,6 +676,8 @@ forward_dir DL_DIR "/downloads" "rw"
forward_dir KAS_REPO_REF_DIR "/repo-ref" "rw"
forward_dir SSTATE_DIR "/sstate" "rw"
forward_dir KAS_BUILDTOOLS_DIR "/buildtools" "rw"
+register_path_rewrite "${KAS_WORK_DIR}" "/work"
+register_path_rewrite "${KAS_REPO_DIR}" "/repo"

if git_com_dir=$(git -C "${KAS_REPO_DIR}" rev-parse --git-common-dir 2>/dev/null) \
&& [ "$git_com_dir" != "$(git -C "${KAS_REPO_DIR}" rev-parse --git-dir)" ]; then
@@ -770,5 +826,10 @@ while [ $KAS_EXTRA_BITBAKE_ARGS -gt 0 ]; do
KAS_EXTRA_BITBAKE_ARGS=$((KAS_EXTRA_BITBAKE_ARGS - 1))
done

-# shellcheck disable=SC2086
-trace ${KAS_CONTAINER_COMMAND} run "$@"
+if [ -n "${KAS_REWRITE}" ] && ! [ -t 1 ]; then
+ # shellcheck disable=SC2086
+ run_with_host_path_rewrite "$@"
+else
+ # shellcheck disable=SC2086
+ trace ${KAS_CONTAINER_COMMAND} run "$@"
+fi
--
2.53.0

Jan Kiszka

unread,
May 7, 2026, 6:56:21 AM (3 days ago) May 7
to Felix Moessbauer, kas-...@googlegroups.com
On 07.05.26 12:02, Felix Moessbauer wrote:
> When running kas / bitbake inside the container, the printed paths point
> into the container instead of the host. While this is technically
> correct, it makes debugging harder as the user manually has to map these
> back to the ones on the host (e.g. on build errors).
>
> We now add the option --rewrite. When enabled, the output of the scripts
> inside the container is captured and all mapped paths are rewritten. We
> do not globally enable it, as capturing the output interfers with TTYs
> (like kas shell, kas menu, oe menuconfig).

"kas menu" is like "kas build" in the end. Either this is robust enough
to handle at least the "menu" case, or we cannot take it.

Also, it should never be provided to kas shell. And it will likely
explode for other interactive tasks as well (devshell...).
Unfortunately, those cannot be detected upfront and are even part of
"kas build" calls.

Last but not least, paths in log files remain containerized.

All these troubles do not look like as if the benefit for (logically)
cutting off "/work" from output logs is worth it.

Jan

--
Siemens AG, Foundational Technologies
Linux Expert Center

MOESSBAUER, Felix

unread,
May 7, 2026, 7:18:38 AM (3 days ago) May 7
to Kiszka, Jan, kas-...@googlegroups.com
On Thu, 2026-05-07 at 12:56 +0200, Jan Kiszka wrote:
> On 07.05.26 12:02, Felix Moessbauer wrote:
> > When running kas / bitbake inside the container, the printed paths point
> > into the container instead of the host. While this is technically
> > correct, it makes debugging harder as the user manually has to map these
> > back to the ones on the host (e.g. on build errors).
> >
> > We now add the option --rewrite. When enabled, the output of the scripts
> > inside the container is captured and all mapped paths are rewritten. We
> > do not globally enable it, as capturing the output interfers with TTYs
> > (like kas shell, kas menu, oe menuconfig).
>
> "kas menu" is like "kas build" in the end. Either this is robust enough
> to handle at least the "menu" case, or we cannot take it.

Well... it's not as it uses different buffering (which is a subtle
difference).


>
> Also, it should never be provided to kas shell. And it will likely
> explode for other interactive tasks as well (devshell...).

Yes.

> Unfortunately, those cannot be detected upfront and are even part of
> "kas build" calls.
>
> Last but not least, paths in log files remain containerized.

Unfortunately yes. But at least when errors are dumped on the console
you can just click on the log.

>
> All these troubles do not look like as if the benefit for (logically)
> cutting off "/work" from output logs is worth it.

That's why it is an RFC. We could also implement the logic in kas
itself, resolving the buffering issues. However, the inconsistency
between the terminal output and the logs remains.

Don't know if it is really worth it.

Felix

Jan Kiszka

unread,
May 7, 2026, 8:37:53 AM (3 days ago) May 7
to Moessbauer, Felix (FT RPD CED OES-DE), kas-...@googlegroups.com
I understand the goal, but the problem is that this approach is not
fully solving it (it can't), and then has some side effects. The latter
might be manageable with user education, but the inconsistencies it will
naturally leave behind may cause as much confusion as different
namespace do today, just elsewhere.

Jörg Sommer

unread,
May 8, 2026, 1:11:29 AM (3 days ago) May 8
to Felix Moessbauer, kas-...@googlegroups.com, jan.k...@siemens.com
'Felix Moessbauer' via kas-devel schrieb am Do 07. Mai, 12:02 (+0200):
> When running kas / bitbake inside the container, the printed paths point
> into the container instead of the host. While this is technically
> correct, it makes debugging harder as the user manually has to map these
> back to the ones on the host (e.g. on build errors).

Pretty good! I am doing the same in my kas-container wrapper, because it I
have the same problem, esp. with scripts running outside and using output
from inside of the container.

One of my mostly used commands are:

kas-container for-all-repos git grep --color "$@"
kas-container for-all-repos git ls-files "$@"

> diff --git a/kas-container b/kas-container
> index a9311e462..cb33ed321 100755
> --- a/kas-container
> +++ b/kas-container
> @@ -85,6 +85,8 @@ usage()
> "container.\n"
> printf "%b" "--git-credential-store\tFile path to the git credential " \
> "store\n"
> + printf "%b" "--rewrite\t\tRewrite container paths to host paths in output\n" \
> + "\t\t\t(may break interactive TTYs inside the container).\n"

The name --rewrite is unspecific. How about --rewrite-paths or --map-paths?
The `&` has no special meaning in regex. But `$` might occur in a path.

If you want to go deeper down this rabbit hole of escaping you might want to
escape the boundary character `|`. But then you have to care for not
creating the `\|` regex sequence. Maybe `@` is a better boundary character,
because it is not part of regex.

> + _esc_to=$(printf '%s\n' "$1" | sed 's/[\\&|]/\\&/g')
> + KAS_OUTPUT_FILTER_RULES="${KAS_OUTPUT_FILTER_RULES}
> +s|${_esc_from}|${_esc_to}|g"

Suggestion: I don't know if the happens more often in the file. I define in
my scripts a variable nl somewhere near the start:

nl='
'
echo "something${nl}with a${nl}newline"
How about doing this in kas in Python? Maybe this would be more robust.
Either using a parameter `--path-map in-container=outside:inside=outside` or
an environment variable KAS_PATH_MAP. This would allow users to add
additional mappings for their own `--runtime-args -v …`.
Why the exclusion of the terminal? I someone sets --rewrite it should also
happen with a terminal.

> + # shellcheck disable=SC2086
> + run_with_host_path_rewrite "$@"

Is the shellcheck exclusion really needed? There is no un-quoted variable.

> +else
> + # shellcheck disable=SC2086
> + trace ${KAS_CONTAINER_COMMAND} run "$@"

In our projects we add an explanation to the excludes like:

# shellcheck disable=SC2086 # K_C_C contains multiple arguments


Best regards, Jörg

--
Navimatix GmbH T: 03641 - 327 99 0
Tatzendpromenade 2 F: 03641 - 526 306
07745 Jena www.navimatix.de

Geschäftsführer: Steffen Späthe, Jan Rommeley
Registergericht: Amtsgericht Jena, HRB 501480
Reply all
Reply to author
Forward
0 new messages