[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: avoid wrapper scripts when possible
From: |
Ricardo Wurmus |
Subject: |
Re: avoid wrapper scripts when possible |
Date: |
Fri, 03 Nov 2017 23:41:44 +0100 |
User-agent: |
mu4e 0.9.18; emacs 25.3.1 |
Ricardo Wurmus <address@hidden> writes:
> Ricardo Wurmus <address@hidden> writes:
>
>> I wonder if there’s a way to have a script header that starts out as a
>> shell script and then calls itself again but skipping over the header,
>> thus calling the original script.
>>
>> Take this Python script as an example:
>>
>> --8<---------------cut here---------------start------------->8---
>> #!/home/rekado/.guix-profile/bin/python
>> print("hello from python")
>> --8<---------------cut here---------------end--------------->8---
>>
>> We then prepend this header:
>>
>> --8<---------------cut here---------------start------------->8---
>> #!/run/current-system/profile/bin/bash
>> echo "hello from bash"
>> exec /home/rekado/.guix-profile/bin/python
>> <(/run/current-system/profile/bin/tail -n +4 "$0")
>> --8<---------------cut here---------------end--------------->8---
>>
>> When we execute the resulting thing it will be a shell script, and do
>> shell things printing “hello from bash”. Then it scrubs itself off the
>> script and removes the original script’s Python shebang using tail (with
>> “-n +4” where 4 is the number of lines of the shell script header + 1),
>> and replaces itself with Python calling the original script.
>>
>> This seems to work just fine […]
>
> Erm, it does not. “$0” becomes a file descriptor like “/dev/fd/63”.
> “exec -a $0” also doesn’t help here.
How about this:
--8<---------------cut here---------------start------------->8---
#!/home/rekado/.guix-profile/bin/guile --no-auto-compile
#!# (let (($0 (car (command-line)))) (execl
"/home/rekado/.guix-profile/bin/python3" $0 $0))
#!/home/rekado/.guix-profile/bin/python3
import sys; print("hello from python: "+sys.argv[0])
--8<---------------cut here---------------end--------------->8---
The first two lines are Guile code, but they are also line comments in
shell, Perl, Python, Ruby, and R. The Guile code in this example calls
the script again as a Python script. Before doing that it can set
environment variables, like so:
--8<---------------cut here---------------start------------->8---
#!/home/rekado/.guix-profile/bin/guile --no-auto-compile
#!#
#\- (setenv "PYTHONPATH" (string-append "/gnu/store/foo:/gnu/store/bar:"
(getenv "PYTHONPATH")))
#\- (let (($0 (car (command-line)))) (execl
"/home/rekado/.guix-profile/bin/python3" $0 $0))
#!/home/rekado/.guix-profile/bin/python3
import sys; print("hello from python: "+sys.argv[0])
print(sys.path)
--8<---------------cut here---------------end--------------->8---
Did I overlook something? Or could we use this hack to remove separate
wrapper scripts for Perl, Python, Ruby, and R?
--
Ricardo
GPG: BCA6 89B6 3655 3801 C3C6 2150 197A 5888 235F ACAC
https://elephly.net
Re: avoid wrapper scripts when possible, Dave Love, 2017/11/06