Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

/bin/sh: 5: source: not found #17

Closed
Timple opened this issue Jun 20, 2022 · 12 comments
Closed

/bin/sh: 5: source: not found #17

Timple opened this issue Jun 20, 2022 · 12 comments

Comments

@Timple
Copy link

Timple commented Jun 20, 2022

Our images in the bitbucket-pipelines have bash as default runner. Can this be adhered?

This does not only affect the source command, which we could easily replace by .. But also environment variables that should be present are not there.

@ktomk
Copy link
Owner

ktomk commented Jun 21, 2022

Good question. /bin/sh has the design decision as we expect every Docker container to have it. This is albeit we're aware that Atlassian Bitbucket Pipelines supports both /bin/sh and /bin/bash (and IIRC prefers /bin/bash if available).

A couple of questions for clarification:

  • Can you share the path of bash in your scenario within the container?
  • Is only the script and after-script execution affected by it? (Copying files, caches and artifacts work?)
  • Can you provide an exemplary pipleines YAML w/ such a script to test with?

We can then figure something out how to better support the bash use-case I'm pretty sure.

The second issue with the environment variables that are not present is less clear to me, perhaps if an exemplary script could show this as well would be helpful to write more.

@ktomk ktomk added enhancement feedback-appreciated curious for feedback and/or responses of open questions labels Jun 21, 2022
@Timple
Copy link
Author

Timple commented Jun 21, 2022

We're using ubuntu dockers as base images (but with bash as SHELL).

  • So path is /bin/bash

  • Yes, no other issues

  • This should do it:

FROM ubuntu:latest
SHELL ["/bin/bash", "-c"] 

docker build -t ubuntu-bash .

image: ubuntu-bash
pipelines:
  default:
    - step:
        name: Build and test
        script:
          - source /etc/os-release
          - echo "$PRETTY_NAME"

@ktomk
Copy link
Owner

ktomk commented Jun 21, 2022

Thanks. Is the PRETTY_NAME parameter non-null in the good case and null/undefined in the reported issue?

@Timple
Copy link
Author

Timple commented Jun 21, 2022

Yes, because the content of /etc/os-release is:

$ cat /etc/os-release 
PRETTY_NAME="Ubuntu 22.04 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
...

(I put the wrong file to source in the example, copy past error. Fixed that now, so please modify in your trials as well)

@ktomk
Copy link
Owner

ktomk commented Jun 21, 2022

Please find a temporary topic branch issue-17-bash in action. Build phar files (choose any) will be kept for two days so they can be used for early user testing.

I target release version 0.0.66 for the new bash runner feature.

@Timple
Copy link
Author

Timple commented Jun 21, 2022

Thank you for taking the time to fix this!
This did fix the example I posted. 🙂

Unfortunately it still doesn't work for our full system. So I've put together a new example :/

FROM ubuntu:latest
RUN echo "HELLO=YOU" > ~/.bashrc
SHELL ["/bin/bash", "-c"]
image: ubuntu-bash
pipelines:
  default:
    - step:
        name: Build and test
        script:
          - echo "$HELLO"
          - source /etc/os-release
          - echo "$PRETTY_NAME"

Now the outcome is the same as from the docker command:

$ docker run ubuntu-bash echo "$HELLO"
<nothing>
$ ~/Downloads/pipelines.phar 
+++ step #1

    name...........: "Build and test"
    effective-image: ubuntu-bash
    container......: pipelines-1.Build-and-test.default.test
    container-id...: 7e400d87b793

+++ copying files into container...


+ echo "$HELLO"


+ source /etc/os-release

+ echo "$PRETTY_NAME"
Ubuntu 22.04 LTS

However, inside the docker:

$ docker run -it ubuntu-bash
root@10dc7d3e3e46:/# echo $HELLO
YOU

So from within the docker all variables declared in the .bashrc file are present. Looks like the pipelines run inside the dockerfile. This might be a completely different concept than what this project is doing?

@ktomk
Copy link
Owner

ktomk commented Jun 21, 2022

docker run -it on (effectively) ubuntu:latest has CMD ["bash"] and loads ~/.bashrc before dropping into the shell prompt.

pipelines runs ubuntu:latest detached with an interactive shell (but /bin/sh) to keep it running. Then it executes the step script via docker exec in the now running pipeline container (this deviates from Atlassian Bitbucket Pipelines and allows keeping the container).

This might be a completely different concept than what this project is doing?

Not sure I understand. From your feedback I read that you'd like to have the environment configured by ~/.bashrc to be loaded. I'll do some tests with that.

You can also inspect what pipelines does by executing with -v (verbose), it shows the docker commands. Additionally with --keep you can keep the container running and then figure out if with docker exec ... $ID/$NAME ... you can already come close to what you're looking for. This would also help me to better understand I guess.

ktomk added a commit that referenced this issue Jun 22, 2022
pipelines is /bin/sh from the ground up. however some scripts need to run
with /bin/bash.

given /bin/bash in the container is an executable file, it is preferred
over /bin/sh by default.

Example pipeline with /bin/bash:

    $ bin/pipelines --pipeline custom/bash-runner --verbatim

    + source /etc/os-release

    + echo "$PRETTY_NAME"
    Ubuntu 22.04 LTS

Example pipeline (previous behaviour):

    $ bin/pipelines -c script.bash-runner=false --pipeline custom/bash-runner --verbatim

    + source /etc/os-release
    /bin/sh: 5: source: not found
    script non-zero exit status: 127

report: #17
ktomk added a commit that referenced this issue Jun 22, 2022
test for ~/.bashrc

---

Looking into the bash runners' `~/.bashrc` issue.

It now seems valid to me that, when using `/bin/bash` as script runner,
to execute (source as in source - not dot - bashism) it if it exists at
the very beginning of the step scripts.

Rationale is the history of the Atlassian Bitbucket Pipelines Plugin.
Before February 2017, scripts were run in an interactive shell. The
Atlassian Bitbucket Pipelines Plugin continued _"to execute the .bashrc
file as if run in an interactive non-login shell but it"_ then behaved
_"as a non-interactive shell"_ ([ref]).


    shell: [interactive,     non-login] | ~>                                          #  February 2017 [ref]
        ~> [non-interactive, non-login]

        +  if [ -f ~/.bashrc ]; then . ~/.bashrc; fi                                  #  from: ref: GNU Bash: [Invoked as an interactive non-login shell]
        +' if [ -f ~/.bashrc ]; then source ~/.bashrc; fi                             #  source (bashism) asserts /bin/bash (over /bin/sh)
        +" test "$0" = "/bin/bash" && if [ -f ~/.bashrc ]; then source ~/.bashrc; fi  #  test for bash runner (/bin/bash)


report: #17
ref: GNU Bash: [Invoked as an interactive non-login shell]
[ref]: https://confluence.atlassian.com/bbkb/infrastructure-changes-in-bitbucket-pipelines-1142431176.html#InfrastructurechangesinBitbucketPipelines-Scriptsarenolongerruninaninteractiveshell
[Invoked as an interactive non-login shell]: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-as-an-interactive-non_002dlogin-shell
@ktomk
Copy link
Owner

ktomk commented Jun 22, 2022

@Timple Did some tests for ~/.bashrc and I think it improves on your use-case:

It now seems valid to me that, when using /bin/bash as script runner, to execute (source as in source - not dot - bashism) it if it exists at the very beginning of the step scripts.

Rationale is the history of the Atlassian Bitbucket Pipelines Plugin. Before February 2017, scripts were run in an interactive shell. The Atlassian Bitbucket Pipelines Plugin continued "to execute the .bashrc file as if run in an interactive non-login shell but it" then behaved "as a non-interactive shell" (ref).

shell: [interactive,     non-login] | ~>                                          #  February 2017 [ref]
    ~> [non-interactive, non-login]

    +  if [ -f ~/.bashrc ]; then . ~/.bashrc; fi                                  #  from: ref: GNU Bash: [Invoked as an interactive non-login shell]
    +' if [ -f ~/.bashrc ]; then source ~/.bashrc; fi                             #  source (bashism) asserts /bin/bash (over /bin/sh)
    +" test "$0" = "/bin/bash" && if [ -f ~/.bashrc ]; then source ~/.bashrc; fi  #  test for bash runner (/bin/bash)

ref: GNU Bash: Invoked as an interactive non-login shell


Please continue to find a temporary topic branch issue-17-bash in action. Build phar files (choose any) will be kept for two days so they can be used for early user testing.

I continue to target release version 0.0.66 for the new bash runner feature.

ktomk added a commit that referenced this issue Jun 22, 2022
test for ~/.bashrc

---

Looking into the bash runners' `~/.bashrc` issue.

It now seems valid to me that, when using `/bin/bash` as script runner,
to execute (source as in source - not dot - bashism) it if it exists at
the very beginning of the step scripts.

Rationale is the history of the Atlassian Bitbucket Pipelines Plugin.
Before February 2017, scripts were run in an interactive shell. The
Atlassian Bitbucket Pipelines Plugin continued _"to execute the .bashrc
file as if run in an interactive non-login shell but it"_ then behaved
_"as a non-interactive shell"_ ([ref]).


    shell: [interactive,     non-login] | ~>                                          #  February 2017 [ref]
        ~> [non-interactive, non-login]

        +  if [ -f ~/.bashrc ]; then . ~/.bashrc; fi                                  #  from: ref: GNU Bash: [Invoked as an interactive non-login shell]
        +' if [ -f ~/.bashrc ]; then source ~/.bashrc; fi                             #  source (bashism) asserts /bin/bash (over /bin/sh)
        +" test "$0" = "/bin/bash" && if [ -f ~/.bashrc ]; then source ~/.bashrc; fi  #  test for bash runner (/bin/bash)


report: #17
ref: GNU Bash: [Invoked as an interactive non-login shell]
[ref]: https://confluence.atlassian.com/bbkb/infrastructure-changes-in-bitbucket-pipelines-1142431176.html#InfrastructurechangesinBitbucketPipelines-Scriptsarenolongerruninaninteractiveshell
[Invoked as an interactive non-login shell]: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-as-an-interactive-non_002dlogin-shell
ktomk added a commit that referenced this issue Jun 22, 2022
pipelines is /bin/sh from the ground up. however some scripts need to run
with /bin/bash.

given /bin/bash in the container is an executable file, it is preferred
over /bin/sh by default.

Example pipeline with /bin/bash:

    $ bin/pipelines --pipeline custom/bash-runner --verbatim

    + source /etc/os-release

    + echo "$PRETTY_NAME"
    Ubuntu 22.04 LTS

Example pipeline (previous behaviour):

    $ bin/pipelines -c script.bash-runner=false --pipeline custom/bash-runner --verbatim

    + source /etc/os-release
    /bin/sh: 5: source: not found
    script non-zero exit status: 127

The bash runner /bin/bash additionally demands support to source .bashrc.

Rationale is the history of the Atlassian Bitbucket Cloud Pipelines Plugin.
Before February 2017, scripts were run in an interactive shell. The
Atlassian Bitbucket Pipelines Plugin continued "to execute the .bashrc
file as if run in an interactive non-login shell but it" then behaved "as
a non-interactive shell" ([ref]).

    shell: [interactive,     non-login] | ~>                                          #  February 2017 [ref]
        ~> [non-interactive, non-login]

        +  if [ -f ~/.bashrc ]; then . ~/.bashrc; fi                                  #  from: ref: GNU Bash: [Invoked as an interactive non-login shell]
        +' if [ -f ~/.bashrc ]; then source ~/.bashrc; fi                             #  source (bashism) asserts /bin/bash (over /bin/sh)
        +" test "$0" = "/bin/bash" && if [ -f ~/.bashrc ]; then source ~/.bashrc; fi  #  test for bash runner (/bin/bash)

report: #17
ref: GNU Bash: [Invoked as an interactive non-login shell]
[ref]: https://confluence.atlassian.com/bbkb/infrastructure-changes-in-bitbucket-pipelines-1142431176.html#InfrastructurechangesinBitbucketPipelines-Scriptsarenolongerruninaninteractiveshell
[Invoked as an interactive non-login shell]: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-as-an-interactive-non_002dlogin-shell
@ktomk
Copy link
Owner

ktomk commented Jun 22, 2022

@Timple if .bashrc is executed, would it then match all of your expectations? Because then I'd say from my end this ready and I'll prepare the next release.

@Timple
Copy link
Author

Timple commented Jun 22, 2022

Awesome, this works! Thank you.

One item left (unrelated so I'll open up a new issue!

@Timple Timple closed this as completed Jun 22, 2022
@ktomk ktomk removed the feedback-appreciated curious for feedback and/or responses of open questions label Jun 22, 2022
ktomk added a commit that referenced this issue Jun 22, 2022
pipelines is /bin/sh from the ground up. however some scripts need to run
with /bin/bash.

given /bin/bash in the container is an executable file, it is preferred
over /bin/sh by default.

Example pipeline with /bin/bash:

    $ bin/pipelines --pipeline custom/bash-runner --verbatim

    + source /etc/os-release

    + echo "$PRETTY_NAME"
    Ubuntu 22.04 LTS

Example pipeline (previous behaviour):

    $ bin/pipelines -c script.bash-runner=false --pipeline custom/bash-runner --verbatim

    + source /etc/os-release
    /bin/sh: 5: source: not found
    script non-zero exit status: 127

The bash runner /bin/bash additionally demands support to source .bashrc.

Rationale is the history of the Atlassian Bitbucket Cloud Pipelines Plugin.
Before February 2017, scripts were run in an interactive shell. The
Atlassian Bitbucket Pipelines Plugin continued "to execute the .bashrc
file as if run in an interactive non-login shell but it" then behaved "as
a non-interactive shell" ([ref]).

    shell: [interactive,     non-login] | ~>                                          #  February 2017 [ref]
        ~> [non-interactive, non-login]

        +  if [ -f ~/.bashrc ]; then . ~/.bashrc; fi                                  #  from: ref: GNU Bash: [Invoked as an interactive non-login shell]
        +' if [ -f ~/.bashrc ]; then source ~/.bashrc; fi                             #  source (bashism) asserts /bin/bash (over /bin/sh)
        +" test "$0" = "/bin/bash" && if [ -f ~/.bashrc ]; then source ~/.bashrc; fi  #  test for bash runner (/bin/bash)

report: #17
ref: GNU Bash: [Invoked as an interactive non-login shell]
[ref]: https://confluence.atlassian.com/bbkb/infrastructure-changes-in-bitbucket-pipelines-1142431176.html#InfrastructurechangesinBitbucketPipelines-Scriptsarenolongerruninaninteractiveshell
[Invoked as an interactive non-login shell]: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-as-an-interactive-non_002dlogin-shell
ktomk added a commit that referenced this issue Jun 22, 2022
pipelines is /bin/sh from the ground up. however some scripts need to run
with /bin/bash.

given /bin/bash in the container is an executable file, it is preferred
over /bin/sh by default.

Example pipeline with /bin/bash:

    $ bin/pipelines --pipeline custom/bash-runner --verbatim

    + source /etc/os-release

    + echo "$PRETTY_NAME"
    Ubuntu 22.04 LTS

Example pipeline (previous behaviour):

    $ bin/pipelines -c script.bash-runner=false --pipeline custom/bash-runner --verbatim

    + source /etc/os-release
    /bin/sh: 5: source: not found
    script non-zero exit status: 127

The bash runner /bin/bash additionally demands support to source .bashrc.

Rationale is the history of the Atlassian Bitbucket Cloud Pipelines Plugin.
Before February 2017, scripts were run in an interactive shell. The
Atlassian Bitbucket Pipelines Plugin continued "to execute the .bashrc
file as if run in an interactive non-login shell but it" then behaved "as
a non-interactive shell" ([ref]).

    shell: [interactive,     non-login] | ~>                                          #  February 2017 [ref]
        ~> [non-interactive, non-login]

        +  if [ -f ~/.bashrc ]; then . ~/.bashrc; fi                                  #  from: ref: GNU Bash: [Invoked as an interactive non-login shell]
        +' if [ -f ~/.bashrc ]; then source ~/.bashrc; fi                             #  source (bashism) asserts /bin/bash (over /bin/sh)
        +" test "$0" = "/bin/bash" && if [ -f ~/.bashrc ]; then source ~/.bashrc; fi  #  test for bash runner (/bin/bash)

report: #17
ref: GNU Bash: [Invoked as an interactive non-login shell]
[ref]: https://confluence.atlassian.com/bbkb/infrastructure-changes-in-bitbucket-pipelines-1142431176.html#InfrastructurechangesinBitbucketPipelines-Scriptsarenolongerruninaninteractiveshell
[Invoked as an interactive non-login shell]: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-as-an-interactive-non_002dlogin-shell
@ktomk
Copy link
Owner

ktomk commented Jun 22, 2022

Released in 0.0.66.

@Timple
Copy link
Author

Timple commented Jun 23, 2022

Rationale is the history of the Atlassian Bitbucket Pipelines Plugin. Before February 2017, scripts were run in an interactive shell. The Atlassian Bitbucket Pipelines Plugin continued "to execute the .bashrc file as if run in an interactive non-login shell but it" then behaved "as a non-interactive shell" (ref).

I only now read this comment (was on phone yesterday). You did an awesome job investiging!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants