diff options
author | Klaus Aehlig <aehlig@google.com> | 2017-08-04 11:49:52 +0200 |
---|---|---|
committer | Dmitry Lomov <dslomov@google.com> | 2017-08-04 17:19:07 +0200 |
commit | 49463f6a1f0971c03fcdfdf9dd03e7445f6ef935 (patch) | |
tree | c936fa890f00ed5659319fa010d70bf1595735bf | |
parent | 028669478cc0054ab51f3dde6738a1269c405ddd (diff) |
Make tests more portable
By replacing uses of /bin/bash by /bin/sh, a tool which is more
reliably at this location. Then, enable most of the bazel tests
for FreeBSD as well.
Change-Id: Ic56a1705858f1ed67d1e96e2937e9389dd1d0e36
PiperOrigin-RevId: 164241635
-rw-r--r-- | scripts/ci/bazel-tests.json | 3 | ||||
-rwxr-xr-x | src/test/shell/bazel/bazel_localtest_test.sh | 2 | ||||
-rwxr-xr-x | src/test/shell/bazel/bazel_repository_cache_test.sh | 4 | ||||
-rwxr-xr-x | src/test/shell/bazel/bazel_rules_test.sh | 4 | ||||
-rwxr-xr-x | src/test/shell/bazel/bazel_test_test.sh | 12 | ||||
-rwxr-xr-x | src/test/shell/bazel/external_integration_test.sh | 54 | ||||
-rwxr-xr-x | src/test/shell/bazel/git_repository_test.sh | 8 | ||||
-rwxr-xr-x | src/test/shell/bazel/local_repository_test.sh | 2 | ||||
-rwxr-xr-x | src/test/shell/bazel/maven_test.sh | 18 | ||||
-rwxr-xr-x | src/test/shell/bazel/process-wrapper_test.sh | 19 | ||||
-rwxr-xr-x | src/test/shell/bazel/remote_helpers.sh | 2 | ||||
-rwxr-xr-x | src/test/shell/bazel/skylark_repository_test.sh | 2 |
12 files changed, 66 insertions, 64 deletions
diff --git a/scripts/ci/bazel-tests.json b/scripts/ci/bazel-tests.json index b12a40da46..535459dec4 100644 --- a/scripts/ci/bazel-tests.json +++ b/scripts/ci/bazel-tests.json @@ -59,7 +59,8 @@ "{} +" ], "tests": [ - "//src/test/shell/integration/..." + "//src/test/shell/integration/...", + "let bazel=\"//src/test/shell/bazel/...\" in $bazel - filter(\"all_tests\", $bazel) - filter(\"jdk\", $bazel) - filter(\"maven\", $bazel) - filter(\"android\", $bazel) - filter(\"java\", $bazel) - filter(\"workspace\", $bazel) - filter(\"external\", $bazel) - filter(\"example\", $bazel) - filter(\"skylark_repository\", $bazel) - filter(\"repository_cache\", $bazel)" ], "targets": [] } diff --git a/src/test/shell/bazel/bazel_localtest_test.sh b/src/test/shell/bazel/bazel_localtest_test.sh index ea592a4ec7..5a387d47f5 100755 --- a/src/test/shell/bazel/bazel_localtest_test.sh +++ b/src/test/shell/bazel/bazel_localtest_test.sh @@ -28,7 +28,7 @@ function test_run_local() { # In standalone mode, # we have access to /var which is not mounted in sandboxed mode cat <<EOF > dir/test_local.sh -#!/bin/bash +#!/bin/sh test -e "$(pwd)/emptyfile" && exit 0 || true echo "no $(pwd)/emptyfile in standalone mode" exit 1 diff --git a/src/test/shell/bazel/bazel_repository_cache_test.sh b/src/test/shell/bazel/bazel_repository_cache_test.sh index e503d683a8..1427817b1b 100755 --- a/src/test/shell/bazel/bazel_repository_cache_test.sh +++ b/src/test/shell/bazel/bazel_repository_cache_test.sh @@ -142,7 +142,7 @@ filegroup( EOF what_does_the_fox_say="Fraka-kaka-kaka-kaka-kow" cat > fox/male <<EOF -#!/bin/bash +#!/bin/sh echo $what_does_the_fox_say EOF chmod +x fox/male @@ -180,7 +180,7 @@ sh_binary( EOF cat > zoo/female.sh <<EOF -#!/bin/bash +#!/bin/sh ../endangered/fox/male EOF chmod +x zoo/female.sh diff --git a/src/test/shell/bazel/bazel_rules_test.sh b/src/test/shell/bazel/bazel_rules_test.sh index 3410ac208e..68c46eff4c 100755 --- a/src/test/shell/bazel/bazel_rules_test.sh +++ b/src/test/shell/bazel/bazel_rules_test.sh @@ -63,7 +63,7 @@ function test_extra_action() { # action file. This file is a proto, but I don't want to bother implementing # a program that parses the proto here. cat > mypkg/echoer.sh <<EOF -#!/bin/bash +#!/bin/sh if [[ ! -e \$0.runfiles/__main__/mypkg/runfile ]]; then echo "Runfile not found" >&2 exit 1 @@ -275,7 +275,7 @@ sh_binary( EOF cat > package/in.sh << EOF -#!/bin/bash +#!/bin/sh echo "Hi" EOF chmod +x package/in.sh diff --git a/src/test/shell/bazel/bazel_test_test.sh b/src/test/shell/bazel/bazel_test_test.sh index 5eb49f9d25..31dfa87da5 100755 --- a/src/test/shell/bazel/bazel_test_test.sh +++ b/src/test/shell/bazel/bazel_test_test.sh @@ -31,7 +31,7 @@ function set_up_jobcount() { mkdir -p dir cat <<EOF > dir/test.sh -#!/bin/bash +#!/bin/sh # hard link z=\$(mktemp -u ${tmp}/tmp.XXXXXXXX) ln ${tmp}/counter \${z} @@ -41,7 +41,7 @@ sleep 1 nlink=\$(ls -l ${tmp}/counter | awk '{print \$2}') # 4 links = 3 jobs + ${tmp}/counter -if [[ "\$nlink" -gt 4 ]] ; then +if [ "\$nlink" -gt 4 ] ; then echo found "\$nlink" hard links to file, want 4 max. exit 1 fi @@ -84,7 +84,7 @@ function test_3_local_jobs() { function DISABLED_test_tmpdir() { mkdir -p foo cat > foo/bar_test.sh <<'EOF' -#!/bin/bash +#!/bin/sh echo TEST_TMPDIR=$TEST_TMPDIR EOF chmod +x foo/bar_test.sh @@ -123,7 +123,7 @@ workspace(name = "bar") EOF mkdir -p foo cat > foo/testenv.sh <<'EOF' -#!/bin/bash +#!/bin/sh echo "pwd: $PWD" echo "src: $TEST_SRCDIR" echo "ws: $TEST_WORKSPACE" @@ -254,8 +254,8 @@ function test_runs_per_test_detects_flakes() { # This file holds the number of the next run echo 1 > "${COUNTER_DIR}/$i" cat <<EOF > test$i.sh -#!/bin/bash -i=\$(< "${COUNTER_DIR}/$i") +#!/bin/sh +i=\$(cat "${COUNTER_DIR}/$i") # increment the hidden state echo \$((i + 1)) > "${COUNTER_DIR}/$i" diff --git a/src/test/shell/bazel/external_integration_test.sh b/src/test/shell/bazel/external_integration_test.sh index 4e1fcd0fec..fb16be7dfe 100755 --- a/src/test/shell/bazel/external_integration_test.sh +++ b/src/test/shell/bazel/external_integration_test.sh @@ -104,7 +104,7 @@ filegroup( EOF what_does_the_fox_say="Fraka-kaka-kaka-kaka-kow" cat > fox/male <<EOF -#!/bin/bash +#!/bin/sh echo $what_does_the_fox_say EOF chmod +x fox/male @@ -125,7 +125,7 @@ EOF cat > WORKSPACE <<EOF http_archive( name = 'endangered', - url = 'http://localhost:$nc_port/$repo2_name', + url = 'http://127.0.0.1:$nc_port/$repo2_name', sha256 = '$sha256' ) EOF @@ -139,7 +139,7 @@ sh_binary( EOF cat > zoo/female.sh <<EOF -#!/bin/bash +#!/bin/sh ../endangered/fox/male EOF chmod +x zoo/female.sh @@ -183,7 +183,7 @@ function test_http_archive_zip() { cat > WORKSPACE <<EOF http_archive( name = 'endangered', - url = 'http://localhost:$nc_port/bleh', + url = 'http://127.0.0.1:$nc_port/bleh', sha256 = '$sha256', type = 'zip', ) @@ -219,7 +219,7 @@ sh_binary( EOF cat > zoo/female.sh <<EOF -#!/bin/bash +#!/bin/sh cat fox/male EOF chmod +x zoo/female.sh @@ -244,7 +244,7 @@ function test_http_archive_mismatched_sha256() { cat > WORKSPACE <<EOF http_archive( name = 'endangered', - url = 'http://localhost:$nc_port/repo.zip', + url = 'http://127.0.0.1:$nc_port/repo.zip', sha256 = '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9826', ) EOF @@ -258,7 +258,7 @@ sh_binary( EOF cat > zoo/female.sh <<EOF -#!/bin/bash +#!/bin/sh cat fox/male EOF chmod +x zoo/female.sh @@ -318,7 +318,7 @@ function test_jar_download() { serve_jar cat > WORKSPACE <<EOF -http_jar(name = 'endangered', url = 'http://localhost:$nc_port/lib.jar') +http_jar(name = 'endangered', url = 'http://127.0.0.1:$nc_port/lib.jar') EOF mkdir -p zoo @@ -350,7 +350,7 @@ function test_http_to_https_redirect() { http_response=$TEST_TMPDIR/http_response cat > $http_response <<EOF HTTP/1.0 301 Moved Permantently -Location: https://localhost:123456789/bad-port-shouldnt-work +Location: https://127.0.0.1:123456789/bad-port-shouldnt-work EOF nc_port=$(pick_random_unused_tcp_port) || exit 1 nc_l $nc_port < $http_response & @@ -360,7 +360,7 @@ EOF cat > WORKSPACE <<EOF http_file( name = 'toto', - url = 'http://localhost:$nc_port/toto', + url = 'http://127.0.0.1:$nc_port/toto', sha256 = '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9826' ) EOF @@ -378,7 +378,7 @@ function test_http_404() { cat > WORKSPACE <<EOF http_file( name = 'toto', - url = 'http://localhost:$nc_port/toto', + url = 'http://127.0.0.1:$nc_port/toto', sha256 = '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9826' ) EOF @@ -391,7 +391,7 @@ EOF function test_http_download() { local test_file=$TEST_TMPDIR/toto cat > $test_file <<EOF -#!/bin/bash +#!/bin/sh echo "Tra-la!" EOF local sha256=$(sha256sum $test_file | cut -f 1 -d ' ') @@ -399,7 +399,7 @@ EOF cd ${WORKSPACE_DIR} cat > WORKSPACE <<EOF -http_file(name = 'toto', url = 'http://localhost:$nc_port/toto', +http_file(name = 'toto', url = 'http://127.0.0.1:$nc_port/toto', sha256 = '$sha256', executable = True) EOF @@ -413,7 +413,7 @@ sh_binary( EOF cat > test/test.sh <<EOF -#!/bin/bash +#!/bin/sh echo "symlink:" ls -l ../toto/file echo "dest:" @@ -434,10 +434,10 @@ function test_http_redirect() { local sha256=$(sha256sum $test_file | cut -f 1 -d ' ') serve_file $test_file cd ${WORKSPACE_DIR} - serve_redirect "http://localhost:$nc_port/toto" + serve_redirect "http://127.0.0.1:$nc_port/toto" cat > WORKSPACE <<EOF -http_file(name = 'toto', url = 'http://localhost:$redirect_port/toto', +http_file(name = 'toto', url = 'http://127.0.0.1:$redirect_port/toto', sha256 = '$sha256') EOF @@ -451,7 +451,7 @@ sh_binary( EOF cat > test/test.sh <<EOF -#!/bin/bash +#!/bin/sh cat ../toto/file/toto EOF @@ -471,7 +471,7 @@ function test_empty_file() { cat > WORKSPACE <<EOF new_http_archive( name = "x", - url = "http://localhost:$nc_port/x.tar.gz", + url = "http://127.0.0.1:$nc_port/x.tar.gz", sha256 = "$sha256", build_file = "x.BUILD", ) @@ -569,7 +569,7 @@ EOF cat > WORKSPACE <<EOF new_http_archive( name = 'endangered', - url = 'http://localhost:$nc_port/repo.zip', + url = 'http://127.0.0.1:$nc_port/repo.zip', sha256 = '$sha256', ${build_file_attr}, ${workspace_file_attr} @@ -586,7 +586,7 @@ sh_binary( EOF cat > zoo/female.sh <<EOF -#!/bin/bash +#!/bin/sh cat ../endangered/fox/male EOF chmod +x zoo/female.sh @@ -604,7 +604,7 @@ function test_fetch() { maven_jar( name = 'endangered', artifact = "com.example.carnivore:carnivore:1.23", - repository = 'http://localhost:$nc_port/', + repository = 'http://127.0.0.1:$nc_port/', sha1 = '$sha1', ) bind(name = 'mongoose', actual = '@endangered//jar') @@ -642,7 +642,7 @@ function test_prefix_stripping_tar_gz() { cat > WORKSPACE <<EOF new_http_archive( name = "x", - url = "http://localhost:$nc_port/x.tar.gz", + url = "http://127.0.0.1:$nc_port/x.tar.gz", sha256 = "$sha256", strip_prefix = "x/y/z", build_file = "x.BUILD", @@ -671,7 +671,7 @@ function test_prefix_stripping_zip() { cat > WORKSPACE <<EOF new_http_archive( name = "x", - url = "http://localhost:$nc_port/x.zip", + url = "http://127.0.0.1:$nc_port/x.zip", sha256 = "$sha256", strip_prefix = "x/y/z", build_file = "x.BUILD", @@ -709,7 +709,7 @@ EOF cat > WORKSPACE <<EOF http_archive( name = "x", - url = "http://localhost:$nc_port/x.zip", + url = "http://127.0.0.1:$nc_port/x.zip", sha256 = "$sha256", strip_prefix = "x/y/z", ) @@ -728,7 +728,7 @@ function test_moving_build_file() { cat > WORKSPACE <<EOF new_http_archive( name = "x", - url = "http://localhost:$nc_port/x.tar.gz", + url = "http://127.0.0.1:$nc_port/x.tar.gz", sha256 = "$sha256", build_file = "x.BUILD", ) @@ -764,7 +764,7 @@ function test_changing_build_file() { cat > WORKSPACE <<EOF new_http_archive( name = "x", - url = "http://localhost:$nc_port/x.tar.gz", + url = "http://127.0.0.1:$nc_port/x.tar.gz", sha256 = "$sha256", build_file = "x.BUILD", ) @@ -834,7 +834,7 @@ EOF cat > remote_ws <<EOF http_archive( name = "repo", - url = "http://localhost:$fileserver_port/repo.zip", + url = "http://127.0.0.1:$fileserver_port/repo.zip", ) EOF external_dir=$(bazel info output_base)/external diff --git a/src/test/shell/bazel/git_repository_test.sh b/src/test/shell/bazel/git_repository_test.sh index 033a6831a2..639d21698f 100755 --- a/src/test/shell/bazel/git_repository_test.sh +++ b/src/test/shell/bazel/git_repository_test.sh @@ -85,7 +85,7 @@ sh_binary( EOF cat > planets/planet_info.sh <<EOF -#!/bin/bash +#!/bin/sh cat ../pluto/info EOF chmod +x planets/planet_info.sh @@ -171,7 +171,7 @@ sh_binary( EOF cat > planets/planet_info.sh <<EOF -#!/bin/bash +#!/bin/sh cat ../pluto/info EOF chmod +x planets/planet_info.sh @@ -246,7 +246,7 @@ sh_binary( EOF cat > planets/planet_info.sh <<EOF -#!/bin/bash +#!/bin/sh cat ../outer_planets/neptune/info cat ../outer_planets/pluto/info EOF @@ -351,7 +351,7 @@ function setup_error_test() { cd $WORKSPACE_DIR mkdir -p planets cat > planets/planet_info.sh <<EOF -#!/bin/bash +#!/bin/sh cat external/pluto/info EOF diff --git a/src/test/shell/bazel/local_repository_test.sh b/src/test/shell/bazel/local_repository_test.sh index b343bbca49..24b759e2d2 100755 --- a/src/test/shell/bazel/local_repository_test.sh +++ b/src/test/shell/bazel/local_repository_test.sh @@ -95,7 +95,7 @@ sh_binary( EOF cat > zoo/dumper.sh <<EOF -#!/bin/bash +#!/bin/sh cat ../pandas/red/baby-panda cat red/day-keeper EOF diff --git a/src/test/shell/bazel/maven_test.sh b/src/test/shell/bazel/maven_test.sh index 3e50d6d204..04e217c6f5 100755 --- a/src/test/shell/bazel/maven_test.sh +++ b/src/test/shell/bazel/maven_test.sh @@ -58,7 +58,7 @@ function test_maven_jar() { maven_jar( name = 'endangered', artifact = "com.example.carnivore:carnivore:1.23", - repository = 'http://localhost:$fileserver_port/', + repository = 'http://127.0.0.1:$fileserver_port/', sha1 = '$sha1', ) bind(name = 'mongoose', actual = '@endangered//jar') @@ -76,7 +76,7 @@ function test_maven_jar_no_sha1() { maven_jar( name = 'endangered', artifact = "com.example.carnivore:carnivore:1.23", - repository = 'http://localhost:$fileserver_port/', + repository = 'http://127.0.0.1:$fileserver_port/', ) bind(name = 'mongoose', actual = '@endangered//jar') EOF @@ -93,7 +93,7 @@ function test_maven_jar_404() { maven_jar( name = 'endangered', artifact = "com.example.carnivore:carnivore:1.23", - repository = 'http://localhost:$nc_port/', + repository = 'http://127.0.0.1:$nc_port/', ) bind(name = 'mongoose', actual = '@endangered//jar') EOF @@ -113,7 +113,7 @@ function test_maven_jar_mismatched_sha1() { maven_jar( name = 'endangered', artifact = "com.example.carnivore:carnivore:1.23", - repository = 'http://localhost:$fileserver_port/', + repository = 'http://127.0.0.1:$fileserver_port/', sha1 = '$wrong_sha1', ) bind(name = 'mongoose', actual = '@endangered//jar') @@ -128,7 +128,7 @@ function test_default_repository() { cat > WORKSPACE <<EOF maven_server( name = "default", - url = "http://localhost:$fileserver_port/", + url = "http://127.0.0.1:$fileserver_port/", ) maven_jar( @@ -146,7 +146,7 @@ function test_settings() { cat > WORKSPACE <<EOF maven_server( name = "x", - url = "http://localhost:$fileserver_port/", + url = "http://127.0.0.1:$fileserver_port/", settings_file = "settings.xml", ) maven_jar( @@ -191,7 +191,7 @@ function test_maven_server_dep() { cat > WORKSPACE <<EOF maven_server( name = "x", - url = "http://localhost:12345/", + url = "http://127.0.0.1:12345/", ) EOF @@ -216,7 +216,7 @@ function test_auth() { cat > WORKSPACE <<EOF maven_server( name = "x", - url = "http://localhost:$fileserver_port/", + url = "http://127.0.0.1:$fileserver_port/", settings_file = "settings.xml", ) maven_jar( @@ -227,7 +227,7 @@ maven_jar( maven_server( name = "y", - url = "http://localhost:$fileserver_port/", + url = "http://127.0.0.1:$fileserver_port/", settings_file = "settings.xml", ) maven_jar( diff --git a/src/test/shell/bazel/process-wrapper_test.sh b/src/test/shell/bazel/process-wrapper_test.sh index 63972acf28..cc71197d4b 100755 --- a/src/test/shell/bazel/process-wrapper_test.sh +++ b/src/test/shell/bazel/process-wrapper_test.sh @@ -46,32 +46,32 @@ function test_basic_functionality() { } function test_to_stderr() { - $process_wrapper --stdout=$OUT --stderr=$ERR /bin/bash -c "/bin/echo hi there >&2" &> $TEST_log || fail + $process_wrapper --stdout=$OUT --stderr=$ERR /bin/sh -c "/bin/echo hi there >&2" &> $TEST_log || fail assert_output "" "hi there" } function test_exit_code() { local code=0 - $process_wrapper --stdout=$OUT --stderr=$ERR /bin/bash -c "exit 71" &> $TEST_log || code=$? + $process_wrapper --stdout=$OUT --stderr=$ERR /bin/sh -c "exit 71" &> $TEST_log || code=$? assert_equals 71 "$code" } function test_signal_death() { local code=0 - $process_wrapper --stdout=$OUT --stderr=$ERR /bin/bash -c 'kill -ABRT $$' &> $TEST_log || code=$? + $process_wrapper --stdout=$OUT --stderr=$ERR /bin/sh -c 'kill -ABRT $$' &> $TEST_log || code=$? assert_equals 134 "$code" # SIGNAL_BASE + SIGABRT = 128 + 6 } function test_signal_catcher() { local code=0 - $process_wrapper --timeout=1 --kill_delay=2 --stdout=$OUT --stderr=$ERR /bin/bash -c \ + $process_wrapper --timeout=1 --kill_delay=2 --stdout=$OUT --stderr=$ERR /bin/sh -c \ 'trap "echo later; exit 0" SIGINT SIGTERM SIGALRM; sleep 10' &> $TEST_log || code=$? assert_equals 142 "$code" # SIGNAL_BASE + SIGALRM = 128 + 14 assert_stdout "later" } function test_basic_timeout() { - $process_wrapper --timeout=1 --kill_delay=2 --stdout=$OUT --stderr=$ERR /bin/bash -c \ + $process_wrapper --timeout=1 --kill_delay=2 --stdout=$OUT --stderr=$ERR /bin/sh -c \ "echo before; sleep 10; echo after" &> $TEST_log && fail assert_stdout "before" } @@ -82,11 +82,12 @@ function test_basic_timeout() { # grace period, thus printing "beforeafter". function test_timeout_grace() { local code=0 - $process_wrapper --timeout=1 --kill_delay=10 --stdout=$OUT --stderr=$ERR /bin/bash -c \ - 'trap "echo -n "before"; sleep 1; echo "after"; exit 0" SIGINT SIGTERM SIGALRM; sleep 10' \ + $process_wrapper --timeout=1 --kill_delay=10 --stdout=$OUT --stderr=$ERR /bin/sh -c \ + 'trap "echo before; sleep 1; echo after; exit 0" SIGINT SIGTERM SIGALRM; sleep 10' \ &> $TEST_log || code=$? assert_equals 142 "$code" # SIGNAL_BASE + SIGALRM = 128 + 14 - assert_stdout "beforeafter" + assert_stdout 'before +after' } # Tests that process_wrapper sends a SIGTERM to a process on timeout, but gives @@ -95,7 +96,7 @@ function test_timeout_grace() { # trap takes longer than the grace period, thus only printing "before". function test_timeout_kill() { local code=0 - $process_wrapper --timeout=1 --kill_delay=2 --stdout=$OUT --stderr=$ERR /bin/bash -c \ + $process_wrapper --timeout=1 --kill_delay=2 --stdout=$OUT --stderr=$ERR /bin/sh -c \ 'trap "echo before; sleep 10; echo after; exit 0" SIGINT SIGTERM SIGALRM; sleep 10' \ &> $TEST_log || code=$? assert_equals 142 "$code" # SIGNAL_BASE + SIGALRM = 128 + 14 diff --git a/src/test/shell/bazel/remote_helpers.sh b/src/test/shell/bazel/remote_helpers.sh index ab8dbd5b6c..7903063c82 100755 --- a/src/test/shell/bazel/remote_helpers.sh +++ b/src/test/shell/bazel/remote_helpers.sh @@ -15,7 +15,7 @@ # limitations under the License. case "${PLATFORM}" in - darwin) + darwin|freebsd) function nc_l() { nc -l $1 } diff --git a/src/test/shell/bazel/skylark_repository_test.sh b/src/test/shell/bazel/skylark_repository_test.sh index 8d92753f9f..d8a4fadde8 100755 --- a/src/test/shell/bazel/skylark_repository_test.sh +++ b/src/test/shell/bazel/skylark_repository_test.sh @@ -339,7 +339,7 @@ function test_skylark_repository_which_and_execute() { # Test we are using the client environment, not the server one bazel info &> /dev/null # Start up the server. - echo "#!/bin/bash" > bin.sh + echo "#!/bin/sh" > bin.sh echo "exit 0" >> bin.sh chmod +x bin.sh |