1.\" $OpenBSD: script.7,v 1.8 2019/08/11 15:48:08 deraadt Exp $ 2.\" 3.\" $NetBSD: script.7,v 1.6 2010/03/22 18:58:32 joerg Exp $ 4.\" 5.\" Copyright (c) 2005 The NetBSD Foundation, Inc. 6.\" All rights reserved. 7.\" 8.\" This document was originally contributed to The NetBSD Foundation 9.\" by Perry E. Metzger of Metzger, Dowdeswell & Co. LLC. 10.\" 11.\" Redistribution and use in source and binary forms, with or without 12.\" modification, are permitted provided that the following conditions 13.\" are met: 14.\" 1. Redistributions of source code must retain the above copyright 15.\" notice, this list of conditions and the following disclaimer. 16.\" 2. Redistributions in binary form must reproduce the above copyright 17.\" notice, this list of conditions and the following disclaimer in the 18.\" documentation and/or other materials provided with the distribution. 19.\" 20.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30.\" POSSIBILITY OF SUCH DAMAGE. 31.\" 32.Dd November 1, 2020 33.Dt SCRIPT 7 34.Os 35.Sh NAME 36.Nm script 37.Nd interpreter script execution 38.Sh DESCRIPTION 39The system is capable of treating a text file containing commands 40intended for an interpreter, such as 41.Xr sh 1 42or 43.Xr awk 1 , 44as an executable program. 45.Pp 46An 47.Dq interpreter script 48is a file which has been set executable (see 49.Xr chmod 2 ) 50and which has a first line of the form: 51.Pp 52.D1 Li #! Ar pathname Op Ar argument 53.Pp 54The 55.Sq #! 56must appear as the first two characters of the file. 57A space between the 58.Sq #! 59and 60.Ar pathname 61is optional. 62At most one 63.Ar argument 64may follow 65.Ar pathname , 66and the length of the entire line is limited (see below). 67.Pp 68If such a file is executed (such as via the 69.Xr execve 2 70system call), the interpreter specified by the 71.Ar pathname 72is executed by the system. 73(The 74.Ar pathname 75is executed without regard to the 76.Ev PATH 77variable, so in general 78.Ar pathname 79should be an absolute path.) 80.Pp 81The arguments passed to the interpreter will be as follows. 82.Va argv[0] 83will be the path to the interpreter itself, as specified on the first 84line of the script. 85If there is an 86.Ar argument 87following 88.Ar pathname 89on the first line of the script, it will be passed as 90.Va argv[1] . 91The subsequent elements of 92.Va argv 93will be the path to the interpreter script file itself (i.e. the 94original 95.Va argv[0] ) 96followed by any further arguments passed when 97.Xr execve 2 98was invoked to execute the script file. 99.Pp 100By convention, it is expected that an interpreter will open the script 101file passed as an argument and process the commands within it. 102Typical interpreters treat 103.Sq # 104as a comment character, and thus will ignore the initial line of the script 105because it begins 106.Sq #! , 107but there is no requirement for this per se. 108.Pp 109On 110.Dx , 111the length of the 112.Sq #! 113line, excluding the 114.Sq #! 115itself, is limited to 116.Dv MAXSHELLCMDLEN 117(as defined in 118.In sys/imgact.h ) . 119Other operating systems impose different limits on the length of 120the 121.Sq #! 122line (see below). 123.Pp 124Note that the interpreter may not itself be an interpreter script. 125If 126.Ar pathname 127does not point to an executable binary, execution of the interpreter 128script will fail. 129.Ss Trampolines and Portable Scripts 130Different operating systems often have interpreters located in 131different locations, and the kernel executes the passed interpreter 132without regard to the setting of environment variables such as 133.Ev PATH . 134This makes it somewhat challenging to set the 135.Sq #! 136line of a script so that it will run identically on different systems. 137.Pp 138Since the 139.Xr env 1 140utility executes a command passed to it on its command line, it is 141often used as a 142.Dq trampoline 143to render scripts portable. 144If the leading line of a script reads 145.Pp 146.Dl #! /usr/bin/env interp 147.Pp 148then the 149.Xr env 1 150command will execute the 151.Dq interp 152command it finds in its 153.Ev PATH , 154passing on to it all subsequent arguments with which it itself was called. 155Since 156.Pa /usr/bin/env 157is found on almost all 158.Tn POSIX 159style systems, this trick is frequently exploited by authors who need 160a script to execute without change on multiple systems. 161.Ss Historical Note: Scripts without `#!' 162Shell scripts predate the invention of the 163.Sq #! 164convention, which is implemented in the kernel. 165In the days of 166.At v7 , 167there was only one interpreter used on the system, 168.Pa /bin/sh , 169and the shell treated any file that failed to execute with an 170.Er ENOEXEC 171error 172(see 173.Xr intro 2 ) 174as a shell script. 175.Pp 176Most shells (such as 177.Xr sh 1 ) 178and certain other facilities (including 179.Xr execlp 3 180and 181.Xr execvp 3 182but not other types of 183.Xr exec 3 184calls) still pass 185interpreter scripts that do not include the 186.Sq #! 187(and thus fail to execute with 188.Er ENOEXEC ) 189to 190.Pa /bin/sh . 191.Pp 192As this behavior is implemented outside the kernel, there is no 193mechanism that forces it to be respected by all programs that execute 194other programs. 195It is thus not completely reliable. 196It is therefore important to always include 197.Pp 198.Dl #!/bin/sh 199.Pp 200in front of Bourne shell scripts, and to treat the traditional 201behavior as obsolete. 202.Sh EXAMPLES 203Suppose that an executable binary exists in 204.Pa /bin/interp 205and that the file 206.Pa /tmp/script 207contains: 208.Bd -literal -offset indent 209#!/bin/interp -arg 210 211[...] 212.Ed 213.Pp 214and that 215.Pa /tmp/script 216is set mode 755. 217.Pp 218Executing 219.Pp 220.Dl $ /tmp/script one two three 221.Pp 222at the shell will result in 223.Pa /bin/interp 224being executed, receiving the following arguments in 225.Va argv 226(numbered from 0): 227.Bd -ragged -offset indent 228.Qq /bin/interp , 229.Qq "-arg" , 230.Qq /tmp/script , 231.Qq one , 232.Qq two , 233.Qq three 234.Ed 235.Ss Portability Note: Multiple arguments 236The behavior of multiple arguments on the 237.Sq #! 238line is highly non-portable between different systems. 239In general, only one argument can be assumed to work consistently. 240.Pp 241Consider the following variation on the previous example. 242Suppose that an executable binary exists in 243.Pa /bin/interp 244and that the file 245.Pa /tmp/script 246contains: 247.Bd -literal -offset indent 248#!/bin/interp -x -y 249 250[...] 251.Ed 252.Pp 253and that 254.Pa /tmp/script 255is set mode 755. 256.Pp 257Executing 258.Pp 259.Dl $ /tmp/script one two three 260.Pp 261at the shell will result in 262.Pa /bin/interp 263being executed, receiving the following arguments in 264.Va argv 265(numbered from 0): 266.Bd -ragged -offset indent 267.Qq /bin/interp , 268.Qq "-x -y" , 269.Qq /tmp/script , 270.Qq one , 271.Qq two , 272.Qq three 273.Ed 274.Pp 275Note that 276.Qq "-x -y" 277will be passed on 278.Dx 279as a single argument. 280.Pp 281Although most 282.Tn POSIX 283style operating systems will pass only one 284.Ar argument , 285the behavior when multiple arguments are included is not 286consistent between platforms. 287Some, such as 288.Dx , 289will concatenate multiple arguments into a single argument (as above), 290some will truncate them, and at least one will pass them as multiple 291arguments. 292.Pp 293The 294.Dx 295behavior is common but not universal. 296Sun's 297.Tn Solaris 298would present the above argument as 299.Qq -x , 300dropping the 301.Qq " -y" 302entirely. 303Perhaps uniquely, recent versions of Apple's 304.Tn OS X 305will actually pass multiple arguments properly, i.e.: 306.Bd -ragged -offset indent 307.Qq /bin/interp , 308.Qq -x , 309.Qq -y , 310.Qq /tmp/script , 311.Qq one , 312.Qq two , 313.Qq three 314.Ed 315.Pp 316The behavior of the system in the face of multiple arguments is thus 317not currently standardized, should not be relied on, and may be 318changed in future releases. 319In general, pass at most one argument, and do not rely on multiple 320arguments being concatenated. 321.Sh SEE ALSO 322.Xr awk 1 , 323.Xr csh 1 , 324.Xr sh 1 , 325.Xr chmod 2 , 326.Xr execve 2 , 327.Xr intro 2 , 328.Xr execlp 3 , 329.Xr execvp 3 330.Sh STANDARDS 331The behavior of interpreter scripts is obliquely referred to, but 332never actually described in, 333.St -p1003.1-2004 . 334.Pp 335The behavior is partially (but not completely) described in the 336.St -svid4 . 337.Pp 338Although it has never been formally standardized, the behavior 339described is largely portable across 340.Tn POSIX 341style systems, with two significant exceptions: the maximum length of the 342.Sq #! 343line, and the behavior if multiple arguments are passed. 344Please be aware that the behavior in the 345face of multiple arguments is not consistent across systems. 346.Sh HISTORY 347The behavior of the kernel when encountering scripts that start in 348.Sq #! 349was not present in 350.At v7 . 351A Usenet posting to net.unix by Guy Harris on October 16, 1984 claims 352that the idea for the 353.Sq #! 354behavior was first proposed by Dennis Ritchie but that the first 355implementation was on 356.Bx . 357.Pp 358Historical manuals (specifically the exec man page) indicate that the 359behavior was present in 360.Bx 4 361at least as early as April, 1981. 362Information on precisely when it was first implemented, and in which 363version of 364.Ux , 365is solicited. 366.Sh CAVEATS 367Numerous security problems are associated with setuid interpreter 368scripts. 369.Pp 370In addition to the fact that many interpreters (and scripts) are 371simply not designed to be robust in a setuid context, a race condition 372exists between the moment that the kernel examines the interpreter 373script file and the moment that the newly invoked interpreter opens 374the file itself. 375.Pp 376Subtle techniques can be used to subvert even seemingly well written scripts. 377Scripts executed by Bourne type shells can be subverted in numerous 378ways, such as by setting the 379.Ev IFS 380variable before executing the script. 381Other interpreters possess their own vulnerabilities. 382Setting the Set-user-ID on execution (SUID) bit 383is therefore very dangerous, and should not be done lightly, if at all. 384