# Useful Julia script tips? (workaround shebang)

**URL:** <https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584>\
**Category:** General Usage\
**Created:** [September 28, 2018, 4:39am UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584 "2018-09-28T04:39:16Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 28, 2018, 4:39am UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/1 "2018-09-28T04:39:16Z")

</div>

I found a useful little hack so I share it here. It may already be discovered elsewhere, but it’s fun to re-discover a nice(?) trick!

If you ever tried to write a julia script and put its options in the shebang, you might notice that [`#!/usr/bin/env` does not work well with options](https://stackoverflow.com/a/4304187) (depending on OS). Of course, you can write a small wrapper in a separate file. But if you want to do it in one file, you can also do:

```julia
#!/bin/bash
# -*- mode: julia -*-
#=
exec julia --color=yes --startup-file=no "${BASH_SOURCE[0]}" "$@"
=#

Base.banner() # put any Julia code here

```

Anything between the first `#=` and `exec` will be executed as the normal bash command. You can do anything there, like setting up environment variables.

Another tip: In Julia 1.x, [you can’t catch `InterruptException` in the script](https://github.com/JuliaLang/julia/pull/29383). However, it is actually capturable in `-e ...` context. So, as a workaround, you can do:

```julia
#!/bin/bash
# -*- mode: julia -*-
#=
exec julia --color=yes --startup-file=no -e "include(popfirst!(ARGS))" "${BASH_SOURCE[0]}" "$@"
=#

@show ARGS
try
    println("sleeping...")
    sleep(10)
catch err
    @show err
finally
    println("woke up")
end

```

Of course, similar multi-language comment hack works between Python and Julia:

```julia
#!/usr/bin/env python
# -*- mode: julia -*-
#=

print("hello from Python!")

import os
cmd = ["julia", __file__]
os.execvp(cmd[0], cmd)

"""
=#

println("hello from Julia!")

#"""

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 28, 2018, 7:42am UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/2 "2018-09-28T07:42:15Z")

</div>

Very neat, thanks! It would be great if the manual had a short section on shebang scripts & Julia, possibly including the above information.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 28, 2018, 8:08am UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/3 "2018-09-28T08:08:00Z")

</div>

I just sent a PR to include the documentation for SIGINT behavior: [https://github.com/JuliaLang/julia/pull/29411](https://github.com/JuliaLang/julia/pull/29411)

I can send another PR for the “shebang” part. I thought maybe this is too hacky for an official documentation, but let’s see… Not sure where to put, though. [https://docs.julialang.org/en/latest/manual/workflow-tips/](https://docs.julialang.org/en/latest/manual/workflow-tips/)? [https://docs.julialang.org/en/latest/manual/faq/](https://docs.julialang.org/en/latest/manual/faq/)?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 28, 2018, 9:12am UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/4 "2018-09-28T09:12:57Z")

</div>

> [@tkf](#):
>
> Not sure where to put, though.

IMO it should go in [Getting started](https://docs.julialang.org/en/stable/manual/getting-started) somewhere, since that is the section that talks about running Julia. Could probably be renamed to “Running Julia” too.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 29, 2018, 3:56am UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/5 "2018-09-29T03:56:31Z")

</div>

Here it goes [Document scripting tips by tkf · Pull Request #29423 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/29423)

---

<div class="post-metadata">

**Author:** ![Lightup1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lightup1/32/35410_2.png) [@Lightup1](https://discourse.julialang.org/u/Lightup1)\
**Post date:** [September 29, 2022, 1:09pm UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/6 "2022-09-29T13:09:40Z")

</div>

When I run `sbatch xxx.jl` file in this way, `include` function will not find the file path by refering to the `xxx.jl` file path.  
Is this a bug?  
Here is the slurm output:

```julia
SystemError: opening file "/tmp/slurmd/QuantumOpticsExtra.jl": No such file or directory

```

The example file tree is this?

```julia
DC_1D
├── figdata
│ └── d_loop_data.jl # file sbatched
├── functions.jl # file needed to include
└── QuantumOpticsExtra.jl # file needed to include

```

example `xxx.jl`

```julia
#!/bin/bash
#SBATCH -N 1
#SBATCH --ntasks-per-node=4
#SBATCH -J test
#SBATCH --cpus-per-task=9 
#SBATCH -p work
#SBATCH --output=slurm/slurm-%x-%j.out
#SBATCH --error=slurm/slurm-%x-%j.out
#=
exec julia -t$SLURM_CPUS_PER_TASK --project=. --color=yes --startup-file=no "${BASH_SOURCE[0]}" "$@"
=#
using Distributed, SlurmClusterManager
addprocs(SlurmManager(),exeflags=["--project=.", "-t$(ENV["SLURM_CPUS_PER_TASK"])", "--color=yes", "--startup-file=no"])
@everywhere include("../QuantumOpticsExtra.jl")

```

---

<div class="post-metadata">

**Author:** ![moble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moble/32/23535_2.png) [@moble](https://discourse.julialang.org/u/moble)\
**Post date:** [October 18, 2022, 2:48pm UTC](https://discourse.julialang.org/t/useful-julia-script-tips-workaround-shebang/15584/7 "2022-10-18T14:48:30Z")

</div>

@Lightup1 I think you’re running into the fact that slurm actually copies your script to a temporary directory when you submit the job. So any files relative to it when you submitted will not be in the same _relative_ place when it runs. I haven’t found an elegant way to deal with this, but this ugly way works. Put something like this immediately above the `exec` command:

```julia
export SLURM_ORIGINAL_COMMAND=$(scontrol show job $SLURM_JOBID | grep "^ Command=" | head -n 1 | cut -d "=" -f 2-)

```

Then in the julia section, you can figure out the directory like this:

```julia
THIS_FILE = if "SLURM_ORIGINAL_COMMAND" ∈ keys(ENV)
    split(lstrip(ENV["SLURM_ORIGINAL_COMMAND"]), " ")[1]
else
    abspath(@ __FILE__ )
end

```

The second case is there in case you want to run the script directly, without slurm.
