xref: /openbsd-src/share/man/man7/script.7 (revision a4e61cf22f1bd8d754dc71c9dc9dfdcdd88ddfb6)
1*a4e61cf2Sjsg.\"	$OpenBSD: script.7,v 1.9 2022/02/06 00:29:02 jsg Exp $
26f6300c6Sjmc.\"
36f6300c6Sjmc.\"	$NetBSD: script.7,v 1.1 2005/05/07 02:20:34 perry Exp $
46f6300c6Sjmc.\"
56f6300c6Sjmc.\" Copyright (c) 2005 The NetBSD Foundation, Inc.
66f6300c6Sjmc.\" All rights reserved.
76f6300c6Sjmc.\"
86f6300c6Sjmc.\" This document was originally contributed to The NetBSD Foundation
96f6300c6Sjmc.\" by Perry E. Metzger of Metzger, Dowdeswell & Co. LLC.
106f6300c6Sjmc.\"
116f6300c6Sjmc.\" Redistribution and use in source and binary forms, with or without
126f6300c6Sjmc.\" modification, are permitted provided that the following conditions
136f6300c6Sjmc.\" are met:
146f6300c6Sjmc.\" 1. Redistributions of source code must retain the above copyright
156f6300c6Sjmc.\"    notice, this list of conditions and the following disclaimer.
166f6300c6Sjmc.\" 2. Redistributions in binary form must reproduce the above copyright
176f6300c6Sjmc.\"    notice, this list of conditions and the following disclaimer in the
186f6300c6Sjmc.\"    documentation and/or other materials provided with the distribution.
196f6300c6Sjmc.\"
206f6300c6Sjmc.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
216f6300c6Sjmc.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
226f6300c6Sjmc.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
236f6300c6Sjmc.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
246f6300c6Sjmc.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
256f6300c6Sjmc.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
266f6300c6Sjmc.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
276f6300c6Sjmc.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
286f6300c6Sjmc.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
296f6300c6Sjmc.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
306f6300c6Sjmc.\" POSSIBILITY OF SUCH DAMAGE.
316f6300c6Sjmc.\"
32*a4e61cf2Sjsg.Dd $Mdocdate: February 6 2022 $
336f6300c6Sjmc.Dt SCRIPT 7
346f6300c6Sjmc.Os
356f6300c6Sjmc.Sh NAME
366f6300c6Sjmc.Nm script
376f6300c6Sjmc.Nd interpreter script execution
386f6300c6Sjmc.Sh DESCRIPTION
396f6300c6SjmcThe system is capable of treating a text file containing commands
406f6300c6Sjmcintended for an interpreter, such as
416f6300c6Sjmc.Xr sh 1
426f6300c6Sjmcor
436f6300c6Sjmc.Xr awk 1 ,
446f6300c6Sjmcas an executable program.
456f6300c6Sjmc.Pp
466f6300c6SjmcAn
476f6300c6Sjmc.Dq interpreter script
486f6300c6Sjmcis a file which has been set executable (see
496f6300c6Sjmc.Xr chmod 2 )
506f6300c6Sjmcand which has a first line of the form:
516f6300c6Sjmc.Pp
526f6300c6Sjmc.D1 Li #! Ar pathname Op Ar argument
536f6300c6Sjmc.Pp
546f6300c6SjmcThe
556f6300c6Sjmc.Sq #!
566f6300c6Sjmcmust appear as the first two characters of the file.
576f6300c6SjmcA space between the
586f6300c6Sjmc.Sq #!
596f6300c6Sjmcand
606f6300c6Sjmc.Ar pathname
616f6300c6Sjmcis optional.
626f6300c6SjmcAt most one
636f6300c6Sjmc.Ar argument
646f6300c6Sjmcmay follow
656f6300c6Sjmc.Ar pathname ,
666f6300c6Sjmcand the length of the entire line is limited (see below).
676f6300c6Sjmc.Pp
686f6300c6SjmcIf such a file is executed (such as via the
696f6300c6Sjmc.Xr execve 2
706f6300c6Sjmcsystem call), the interpreter specified by the
716f6300c6Sjmc.Ar pathname
726f6300c6Sjmcis executed by the system.
736f6300c6Sjmc(The
746f6300c6Sjmc.Ar pathname
756f6300c6Sjmcis executed without regard to the
766f6300c6Sjmc.Ev PATH
776f6300c6Sjmcvariable, so in general
786f6300c6Sjmc.Ar pathname
796f6300c6Sjmcshould be an absolute path.)
806f6300c6Sjmc.Pp
816f6300c6SjmcThe arguments passed to the interpreter will be as follows.
826f6300c6Sjmc.Va argv[0]
836f6300c6Sjmcwill be the path to the interpreter itself, as specified on the first
846f6300c6Sjmcline of the script.
856f6300c6SjmcIf there is an
866f6300c6Sjmc.Ar argument
876f6300c6Sjmcfollowing
886f6300c6Sjmc.Ar pathname
896f6300c6Sjmcon the first line of the script, it will be passed as
906f6300c6Sjmc.Va argv[1] .
916f6300c6SjmcThe subsequent elements of
926f6300c6Sjmc.Va argv
936f6300c6Sjmcwill be the path to the interpreter script file itself (i.e. the
946f6300c6Sjmcoriginal
956f6300c6Sjmc.Va argv[0] )
966f6300c6Sjmcfollowed by any further arguments passed when
976f6300c6Sjmc.Xr execve 2
986f6300c6Sjmcwas invoked to execute the script file.
996f6300c6Sjmc.Pp
1006f6300c6SjmcBy convention, it is expected that an interpreter will open the script
1016f6300c6Sjmcfile passed as an argument and process the commands within it.
1026f6300c6SjmcTypical interpreters treat
1036f6300c6Sjmc.Sq #
1046f6300c6Sjmcas a comment character, and thus will ignore the initial line of the script
1056f6300c6Sjmcbecause it begins
1066f6300c6Sjmc.Sq #! ,
1076f6300c6Sjmcbut there is no requirement for this per se.
1086f6300c6Sjmc.Pp
1096f6300c6SjmcOn
1106f6300c6Sjmc.Ox ,
1115cf31938Sdjmthe length of the interpreter line following the
1126f6300c6Sjmc.Sq #!
1135cf31938Sdjmis limited to
1146f6300c6Sjmc.Dv MAXINTERP ,
1156f6300c6Sjmcas defined in
116369bef3aSschwarze.In sys/param.h .
1176f6300c6SjmcOther operating systems impose different limits on the length of
1186f6300c6Sjmcthe
1196f6300c6Sjmc.Sq #!
1206f6300c6Sjmcline (see below).
1216f6300c6Sjmc.Pp
1226f6300c6SjmcNote that the interpreter may not itself be an interpreter script.
1236f6300c6SjmcIf
1246f6300c6Sjmc.Ar pathname
1256f6300c6Sjmcdoes not point to an executable binary, execution of the interpreter
1266f6300c6Sjmcscript will fail.
1276f6300c6Sjmc.Ss Trampolines and Portable Scripts
1286f6300c6SjmcDifferent operating systems often have interpreters located in
1296f6300c6Sjmcdifferent locations, and the kernel executes the passed interpreter
1306f6300c6Sjmcwithout regard to the setting of environment variables such as
1316f6300c6Sjmc.Ev PATH .
1326f6300c6SjmcThis makes it somewhat challenging to set the
1336f6300c6Sjmc.Sq #!
1346f6300c6Sjmcline of a script so that it will run identically on different systems.
1356f6300c6Sjmc.Pp
1366f6300c6SjmcSince the
1376f6300c6Sjmc.Xr env 1
1386f6300c6Sjmcutility executes a command passed to it on its command line, it is
1396f6300c6Sjmcoften used as a
1406f6300c6Sjmc.Dq trampoline
1416f6300c6Sjmcto render scripts portable.
1426f6300c6SjmcIf the leading line of a script reads
1436f6300c6Sjmc.Pp
1446f6300c6Sjmc.Dl #! /usr/bin/env interp
1456f6300c6Sjmc.Pp
1466f6300c6Sjmcthen the
1476f6300c6Sjmc.Xr env 1
1486f6300c6Sjmccommand will execute the
1496f6300c6Sjmc.Dq interp
1506f6300c6Sjmccommand it finds in its
1516f6300c6Sjmc.Ev PATH ,
1526f6300c6Sjmcpassing on to it all subsequent arguments with which it itself was called.
1536f6300c6SjmcSince
1546f6300c6Sjmc.Pa /usr/bin/env
1556f6300c6Sjmcis found on almost all
1566f6300c6Sjmc.Tn POSIX
1576f6300c6Sjmcstyle systems, this trick is frequently exploited by authors who need
1586f6300c6Sjmca script to execute without change on multiple systems.
1596f6300c6Sjmc.Ss Historical Note: Scripts without `#!'
1606f6300c6SjmcShell scripts predate the invention of the
1616f6300c6Sjmc.Sq #!
1626f6300c6Sjmcconvention, which is implemented in the kernel.
1636f6300c6SjmcIn the days of
1646f6300c6Sjmc.At v7 ,
1656f6300c6Sjmcthere was only one interpreter used on the system,
1666f6300c6Sjmc.Pa /bin/sh ,
1676f6300c6Sjmcand the shell treated any file that failed to execute with an
1686f6300c6Sjmc.Er ENOEXEC
1696f6300c6Sjmcerror
1706f6300c6Sjmc(see
1716f6300c6Sjmc.Xr intro 2 )
1726f6300c6Sjmcas a shell script.
1736f6300c6Sjmc.Pp
1746f6300c6SjmcMost shells (such as
1756f6300c6Sjmc.Xr sh 1 )
1766f6300c6Sjmcand certain other facilities (including
1776f6300c6Sjmc.Xr execlp 3
1786f6300c6Sjmcand
179d4db6826Sderaadt.Xr execvp 3 )
180d4db6826Sderaadtstill pass interpreter scripts that do not include the
1816f6300c6Sjmc.Sq #!
1826f6300c6Sjmc(and thus fail to execute with
1836f6300c6Sjmc.Er ENOEXEC )
1846f6300c6Sjmcto
1856f6300c6Sjmc.Pa /bin/sh .
1866f6300c6Sjmc.Pp
1876f6300c6SjmcAs this behavior is implemented outside the kernel, there is no
1886f6300c6Sjmcmechanism that forces it to be respected by all programs that execute
1896f6300c6Sjmcother programs.
1906f6300c6SjmcIt is thus not completely reliable.
1916f6300c6SjmcIt is therefore important to always include
1926f6300c6Sjmc.Pp
1936f6300c6Sjmc.Dl #!/bin/sh
1946f6300c6Sjmc.Pp
1956f6300c6Sjmcin front of Bourne shell scripts, and to treat the traditional
1966f6300c6Sjmcbehavior as obsolete.
1976f6300c6Sjmc.Sh EXAMPLES
1986f6300c6SjmcSuppose that an executable binary exists in
1996f6300c6Sjmc.Pa /bin/interp
2006f6300c6Sjmcand that the file
2016f6300c6Sjmc.Pa /tmp/script
2026f6300c6Sjmccontains:
2036f6300c6Sjmc.Bd -literal -offset indent
2046f6300c6Sjmc#!/bin/interp -arg
2056f6300c6Sjmc
2066f6300c6Sjmc[...]
2076f6300c6Sjmc.Ed
2086f6300c6Sjmc.Pp
2096f6300c6Sjmcand that
2106f6300c6Sjmc.Pa /tmp/script
2116f6300c6Sjmcis set mode 755.
2126f6300c6Sjmc.Pp
2136f6300c6SjmcExecuting
2146f6300c6Sjmc.Pp
2156f6300c6Sjmc.Dl $ /tmp/script one two three
2166f6300c6Sjmc.Pp
2176f6300c6Sjmcat the shell will result in
2186f6300c6Sjmc.Pa /bin/interp
2196f6300c6Sjmcbeing executed, receiving the following arguments in
2206f6300c6Sjmc.Va argv
2216f6300c6Sjmc(numbered from 0):
2226f6300c6Sjmc.Bd -ragged -offset indent
2236f6300c6Sjmc.Qq /bin/interp ,
2246f6300c6Sjmc.Qq "-arg" ,
2256f6300c6Sjmc.Qq /tmp/script ,
2266f6300c6Sjmc.Qq one ,
2276f6300c6Sjmc.Qq two ,
2286f6300c6Sjmc.Qq three
2296f6300c6Sjmc.Ed
2306f6300c6Sjmc.Ss Portability Note: Multiple arguments
2316f6300c6SjmcThe behavior of multiple arguments on the
2326f6300c6Sjmc.Sq #!
2336f6300c6Sjmcline is highly non-portable between different systems.
2346f6300c6SjmcIn general, only one argument can be assumed to work consistently.
2356f6300c6Sjmc.Pp
2366f6300c6SjmcConsider the following variation on the previous example.
2376f6300c6SjmcSuppose that an executable binary exists in
2386f6300c6Sjmc.Pa /bin/interp
2396f6300c6Sjmcand that the file
2406f6300c6Sjmc.Pa /tmp/script
2416f6300c6Sjmccontains:
2426f6300c6Sjmc.Bd -literal -offset indent
2436f6300c6Sjmc#!/bin/interp -x -y
2446f6300c6Sjmc
2456f6300c6Sjmc[...]
2466f6300c6Sjmc.Ed
2476f6300c6Sjmc.Pp
2486f6300c6Sjmcand that
2496f6300c6Sjmc.Pa /tmp/script
2506f6300c6Sjmcis set mode 755.
2516f6300c6Sjmc.Pp
2526f6300c6SjmcExecuting
2536f6300c6Sjmc.Pp
2546f6300c6Sjmc.Dl $ /tmp/script one two three
2556f6300c6Sjmc.Pp
2566f6300c6Sjmcat the shell will result in
2576f6300c6Sjmc.Pa /bin/interp
2586f6300c6Sjmcbeing executed, receiving the following arguments in
2596f6300c6Sjmc.Va argv
2606f6300c6Sjmc(numbered from 0):
2616f6300c6Sjmc.Bd -ragged -offset indent
2626f6300c6Sjmc.Qq /bin/interp ,
2636f6300c6Sjmc.Qq "-x -y" ,
2646f6300c6Sjmc.Qq /tmp/script ,
2656f6300c6Sjmc.Qq one ,
2666f6300c6Sjmc.Qq two ,
2676f6300c6Sjmc.Qq three
2686f6300c6Sjmc.Ed
2696f6300c6Sjmc.Pp
2706f6300c6SjmcNote that
2716f6300c6Sjmc.Qq "-x -y"
2726f6300c6Sjmcwill be passed on
2736f6300c6Sjmc.Ox
2746f6300c6Sjmcas a single argument.
2756f6300c6Sjmc.Pp
2766f6300c6SjmcAlthough most
2776f6300c6Sjmc.Tn POSIX
2786f6300c6Sjmcstyle operating systems will pass only one
2796f6300c6Sjmc.Ar argument ,
2805f7a33e3Sjaredythe behavior when multiple arguments are included is not
2816f6300c6Sjmcconsistent between platforms.
2826f6300c6SjmcSome, such as
2836f6300c6Sjmc.Ox ,
2846f6300c6Sjmcwill concatenate multiple arguments into a single argument (as above),
2856f6300c6Sjmcsome will truncate them, and at least one will pass them as multiple
2866f6300c6Sjmcarguments.
2876f6300c6Sjmc.Pp
2886f6300c6SjmcThe
2896f6300c6Sjmc.Ox
2906f6300c6Sjmcbehavior is common but not universal.
2916f6300c6SjmcSun's
2926f6300c6Sjmc.Tn Solaris
2936f6300c6Sjmcwould present the above argument as
2946f6300c6Sjmc.Qq -x ,
2956f6300c6Sjmcdropping the
2966f6300c6Sjmc.Qq " -y"
2976f6300c6Sjmcentirely.
2986f6300c6SjmcPerhaps uniquely, recent versions of Apple's
2996f6300c6Sjmc.Tn OS X
3006f6300c6Sjmcwill actually pass multiple arguments properly, i.e.:
3016f6300c6Sjmc.Bd -ragged -offset indent
3026f6300c6Sjmc.Qq /bin/interp ,
3036f6300c6Sjmc.Qq -x ,
3046f6300c6Sjmc.Qq -y ,
3056f6300c6Sjmc.Qq /tmp/script ,
3066f6300c6Sjmc.Qq one ,
3076f6300c6Sjmc.Qq two ,
3086f6300c6Sjmc.Qq three
3096f6300c6Sjmc.Ed
3106f6300c6Sjmc.Pp
3116f6300c6SjmcThe behavior of the system in the face of multiple arguments is thus
3126f6300c6Sjmcnot currently standardized, should not be relied on, and may be
3136f6300c6Sjmcchanged in future releases.
3146f6300c6SjmcIn general, pass at most one argument, and do not rely on multiple
3156f6300c6Sjmcarguments being concatenated.
3166f6300c6Sjmc.Sh SEE ALSO
3176f6300c6Sjmc.Xr awk 1 ,
3186f6300c6Sjmc.Xr csh 1 ,
3196f6300c6Sjmc.Xr ksh 1 ,
3206f6300c6Sjmc.Xr sh 1 ,
3216f6300c6Sjmc.Xr chmod 2 ,
3226f6300c6Sjmc.Xr execve 2 ,
3236f6300c6Sjmc.Xr intro 2 ,
3246f6300c6Sjmc.Xr execlp 3 ,
3256f6300c6Sjmc.Xr execvp 3
3266f6300c6Sjmc.Sh STANDARDS
3276f6300c6SjmcThe behavior of interpreter scripts is obliquely referred to, but
3286f6300c6Sjmcnever actually described in,
329af69310cSjmc.St -p1003.1-2004 .
3306f6300c6Sjmc.Pp
3316f6300c6SjmcThe behavior is partially (but not completely) described in the
3326f6300c6Sjmc.St -svid4 .
3336f6300c6Sjmc.Pp
3346f6300c6SjmcAlthough it has never been formally standardized, the behavior
3356f6300c6Sjmcdescribed is largely portable across
3366f6300c6Sjmc.Tn POSIX
3376f6300c6Sjmcstyle systems, with two significant exceptions: the maximum length of the
3386f6300c6Sjmc.Sq #!
3396f6300c6Sjmcline, and the behavior if multiple arguments are passed.
340*a4e61cf2SjsgBe aware that the behavior in the
3416f6300c6Sjmcface of multiple arguments is not consistent across systems.
3426f6300c6Sjmc.Sh HISTORY
3436f6300c6SjmcThe behavior of the kernel when encountering scripts that start in
3446f6300c6Sjmc.Sq #!
3456f6300c6Sjmcwas not present in
3466f6300c6Sjmc.At v7 .
3476f6300c6SjmcA Usenet posting to net.unix by Guy Harris on October 16, 1984 claims
3486f6300c6Sjmcthat the idea for the
3496f6300c6Sjmc.Sq #!
3506f6300c6Sjmcbehavior was first proposed by Dennis Ritchie but that the first
3516f6300c6Sjmcimplementation was on
3526f6300c6Sjmc.Bx .
3536f6300c6Sjmc.Pp
3546f6300c6SjmcHistorical manuals (specifically the exec man page) indicate that the
3556f6300c6Sjmcbehavior was present in
3566f6300c6Sjmc.Bx 4
3576f6300c6Sjmcat least as early as April, 1981.
3586f6300c6SjmcInformation on precisely when it was first implemented, and in which
3596f6300c6Sjmcversion of
3606f6300c6Sjmc.Ux ,
3616f6300c6Sjmcis solicited.
3626f6300c6Sjmc.Sh CAVEATS
3636f6300c6SjmcNumerous security problems are associated with setuid interpreter
3646f6300c6Sjmcscripts.
3656f6300c6Sjmc.Pp
3666f6300c6SjmcIn addition to the fact that many interpreters (and scripts) are
3676f6300c6Sjmcsimply not designed to be robust in a setuid context, a race condition
3686f6300c6Sjmcexists between the moment that the kernel examines the interpreter
3696f6300c6Sjmcscript file and the moment that the newly invoked interpreter opens
3706f6300c6Sjmcthe file itself.
3716f6300c6Sjmc.Pp
3726f6300c6SjmcSubtle techniques can be used to subvert even seemingly well written scripts.
3736f6300c6SjmcScripts executed by Bourne type shells can be subverted in numerous
3746f6300c6Sjmcways, such as by setting the
3756f6300c6Sjmc.Ev IFS
3766f6300c6Sjmcvariable before executing the script.
3776f6300c6SjmcOther interpreters possess their own vulnerabilities.
3786f6300c6SjmcSetting the Set-user-ID on execution (SUID) bit
3796f6300c6Sjmcis therefore very dangerous, and should not be done lightly, if at all.
380