Home > Software engineering >  What is the difference of writing to files using ">>" vs using linefeed character &q
What is the difference of writing to files using ">>" vs using linefeed character &q

Time:05-05

I have observed that kubectl inserts an additional \ to linefeed characters when using the --from-literal option. It works as expected when loading "the same" content from a file. Clearly, there must be a difference because the stdout looks different but I fail to see why.

echo "api_key" >> .tmp
echo "api_value" >> .tmp
cat -e .tmp
kubectl delete secrets api-env
kubectl create secret generic api-env --from-file=.api=.tmp
rm .tmp
kubectl get secret api-env -o json | jq '.data | map_values(@base64d)'

#prints:
#api_key$
#api_value$
#secret "api-env" deleted
#secret/api-env created
#{
#  ".api": "api_key\napi_value\n"
#}

The commands above create a single linefeed character on each line. Demonstrated by cat -e there are two linefeed characters in the file, each at the end.

Doing the same using a string results in the \n to be escaped.

api="api_key\napi_value\n"
echo $api
kubectl delete secrets api-env
kubectl create secret generic api-env --from-literal=.api=$api
kubectl get secret api-env -o json | jq '.data | map_values(@base64d)'

#prints:
#api_key\napi_value\n
#secret "api-env" deleted
#secret/api-env created
#{
#  ".api": "api_key\\napi_value\\n"
#}

The echo command shows the string as it was supplied to the variable, however after loading that to kubernetes the \n are escaped and the content is considered to be a single line.

This is important because in several instances where I am working with kubectl I am not allowed to write to the local file system.

What is happening here and how to stop kubernetes from escaping the \n character?

Environment:

  • zsh 5.8 (x86_64-apple-darwin21.0)
  • Darwin Kernel Version 21.4.0: root:xnu-8020.101.4~15/RELEASE_X86_64 x86_64
  • kubectl Client:"v1.20.10"
  • kubectl Server: "v1.23.3"
  • minikube version: v1.25.2

CodePudding user response:

When you use echo $api, echo itself changes the contents: On POSIX-compliant shells with XSI extensions enabled (and while zsh isn't POSIX-compliant in general, it does implement this aspect), the \ns are replaced with literal newlines.

That doesn't happen with --from-literal=.api=$api; there, your \ns are still two-character sequences, first a backslash, then a n.

Given that you're on a shell that supports using $'\n' as a way to represent a newline literal directly, consider --from-literal=.api="api_key"$'\n'"api_value"

  • Related