{"id":421,"date":"2016-02-08T13:57:06","date_gmt":"2016-02-08T12:57:06","guid":{"rendered":"https:\/\/blogs.gentoo.org\/mgorny\/?p=421"},"modified":"2016-02-08T16:36:29","modified_gmt":"2016-02-08T15:36:29","slug":"a-quick-note-on-portable-shebangs","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/mgorny\/2016\/02\/08\/a-quick-note-on-portable-shebangs\/","title":{"rendered":"A quick note on portable shebangs"},"content":{"rendered":"<p>While at\u00a0first shebangs may seem pretty obvious and\u00a0well supported, there is a\u00a0number of not-so-well-known portability issues affecting them. Only during my recent development work, I have hit more than one of\u00a0them. For this reason, I&#8217;d like to write a\u00a0quick note summarizing how to stay on the\u00a0safe side and\u00a0keep your scripts working across various systems.<\/p>\n<p>Please note I will only cover the\u00a0basic solution to the\u00a0most important portability issues. If you&#8217;d like to know more about shebang handling in\u00a0various systems, I&#8217;d like to recommend you an\u00a0excellent article <a rel='external' href='http:\/\/www.in-ulm.de\/~mascheck\/various\/shebang\/'>\u2018The #! magic, details about the shebang\/hash-bang mechanism on various Unix flavours\u2019<\/a> by\u00a0Sven Mascheck.<\/p>\n<p><!--more--><\/p>\n<p>So, in\u00a0order to stay portable you should note that:<\/p>\n<ol>\n<li>Many systems (Linux included!) have limits on\u00a0shebang length. If you exceed this length, the\u00a0kernel will cut the\u00a0shebang in\u00a0the\u00a0middle of\u00a0a\u00a0path component, and\u00a0usually try to execute the\u00a0script with the\u00a0partial path! To stay safe you need to keep shebang short. Since you can&#8217;t really control where the\u00a0programs are installed (think of\u00a0Prefix!), you should always rely on\u00a0<kbd>PATH<\/kbd> lookups.<\/li>\n<li>Shebangs do not have built-in <kbd>PATH<\/kbd> lookups. Instead, you have to use the\u00a0<kbd>\/usr\/bin\/env<\/kbd> tool which performs the\u00a0lookup on its argument (the\u00a0exact path is <em>mostly<\/em> portable, with a\u00a0few historical exceptions).<\/li>\n<li>Different systems split parameters in\u00a0shebangs differently. In\u00a0particular, Linux splits on the\u00a0first space only, passing everything following it as a\u00a0single parameter. To stay portable, you can not pass more than one parameter, and\u00a0it can not contain whitespace. Which \u2014 considering the\u00a0previous points made \u2014 means the\u00a0parameter is reserved for program name passed to <kbd>env<\/kbd>, and\u00a0you can not pass any actual parameters.<\/li>\n<li>Shebang nesting (i.e.\u00a0referencing an\u00a0interpreted script inside a\u00a0shebang) is supported only by\u00a0some systems, and\u00a0only to some extent. For this reason, shebangs need to reference actual executable programs. However, using <kbd>env<\/kbd> effectively works around the\u00a0issue since <kbd>env<\/kbd> is the\u00a0immediate interpreter.<\/li>\n<\/ol>\n<p>A\u00a0few quick examples:<\/p>\n<pre><code><span style='color: green'>#!\/usr\/bin\/env python  # GOOD!<\/span>\r\n\r\n<span style='color: red'>#!python  # BAD: won't work\r\n\r\n#!\/usr\/bin\/env python -b  # BAD: it may try to spawn program named 'python -b'\r\n\r\n#!\/usr\/bin\/python  # BAD: absolute path is non-portable, also see below\r\n\r\n#!\/foo\/bar\/baz\/usr\/bin\/python  # BAD: prefix can easily exceed length limit\r\n\r\n#!\/usr\/lib\/foo\/foo.sh  # BAD: calling interpreted scripts is non-portable<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>While at\u00a0first shebangs may seem pretty obvious and\u00a0well supported, there is a\u00a0number of not-so-well-known portability issues affecting them. Only during my recent development work, I have hit more than one of\u00a0them. For this reason, I&#8217;d like to write a\u00a0quick note summarizing how to stay on the\u00a0safe side and\u00a0keep your scripts working across various systems. Please &hellip; <a href=\"https:\/\/blogs.gentoo.org\/mgorny\/2016\/02\/08\/a-quick-note-on-portable-shebangs\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;A quick note on portable shebangs&#8221;<\/span><\/a><\/p>\n","protected":false},"author":137,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[3,8],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/421"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/users\/137"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/comments?post=421"}],"version-history":[{"count":11,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/421\/revisions"}],"predecessor-version":[{"id":433,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/421\/revisions\/433"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/media?parent=421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/categories?post=421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/tags?post=421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}