{"id":3166,"date":"2022-12-11T00:26:19","date_gmt":"2022-12-11T05:26:19","guid":{"rendered":"https:\/\/blog.jonesling.us\/?p=3166"},"modified":"2022-12-24T09:43:52","modified_gmt":"2022-12-24T14:43:52","slug":"cant-call-method-stat-on-an-undefined-value","status":"publish","type":"post","link":"https:\/\/blog.jonesling.us\/?p=3166","title":{"rendered":"Can&#8217;t call method &#8220;stat&#8221; on an undefined value"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I use <a href=\"https:\/\/www.rexify.org\/index.html\">Rexify<\/a> to manage my servers. (I&#8217;m learning to treat my servers like cattle, not pets.) I have it distributing standardized config files, running updates, and more.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After adding a Raspberry Pi-based system to manage my backups, I was plagued with this error:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;2022-12-10 23:41:13] INFO - Running task Config:System:standard on backup\n&#x5B;2022-12-10 23:41:15] ERROR - Error executing task:\n&#x5B;2022-12-10 23:41:15] ERROR - Can&#039;t call method &quot;stat&quot; on an undefined value at \/usr\/lib64\/perl5\/vendor_perl\/5.34\/Rex\/Interface\/Fs\/OpenSSH.pm line 70, &amp;lt;&gt; line 144.\n&#x5B;2022-12-10 23:41:15] ERROR - 1 out of 1 task(s) failed: \n&#x5B;2022-12-10 23:41:15] ERROR - Config:System:standard failed on backup\n&#x5B;2022-12-10 23:41:15] ERROR - Can&#039;t call method &quot;stat&quot; on an undefined value at \/usr\/lib64\/perl5\/vendor_perl\/5.34\/Rex\/Interface\/Fs\/OpenSSH.pm line 70, &amp;lt;&gt; line 144.\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The error didn&#8217;t make much sense, and wasn&#8217;t consistent. Not all Rex commands triggered it.  When I did run into it, the same command executed directly on the server worked just fine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Just to be clear:<\/strong> the problem had nothing to do with the system architecture.  I.e. the fact that it was a Raspberry Pi, or an ARM device generally, was a red herring, but this was the first RPi that I had managed with Rex, and the only system with this problem, so I didn&#8217;t rule it out right away.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Diagnosis<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At first glance it appeared to be a bug in Rex, because that was the only thing that made sense.  Why would it be complaining that it can&#8217;t call &#8220;stat&#8221; on an undefined file path, when the files are all clearly defined in my Rexfile configuration?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The line number referred to a place where Rex calls stat using SFTP.  The actual value of $path was unknown to me, as I didn&#8217;t want to immediately jump into someone else&#8217;s code and start outputting debug info, but it seemed reasonable that it would either be the local or remote file, and the files should be clearly defined.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: perl; title: ; notranslate\" title=\"\">\nmy $attr = $sftp-&gt;stat($path);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">That seems pretty straight-forward.  If this <em>is<\/em> a bug in Rex then other people should be encountering it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Googling the error was rather unhelpful.  That specific error, with quotes to search exact matches, returned no hits.  An inexact match returned nothing helpful.  Nothing about Rex, just a bunch of other applications doing other things.  Let&#8217;s set that assumption aside and look elsewhere.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I could run simple commands using Rex, like &#8216;uptime&#8217;, to the server but more complicated things were a problem.  The only common thread so far involved putting files.  Could it be an issue with sending and receiving files?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rex is configured to connect as root, there aren&#8217;t other users on the system (besides default and service accounts) to accidentally connect as, and the paths are all regular filesystem paths (not \/dev or similar), so it&#8217;s almost certainly not a permissions issue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Maybe a second SSH connection couldn&#8217;t be established; SFTP establishes an SSH connection and tunnels across it, after all.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I don&#8217;t set a common ControlMaster and ControlPath setting in my config, but I know from experience that if you do, and you force the first (&#8220;master&#8221;) to close, you&#8217;ll knock out other connections to the same host.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Well, I could connect via SSH just fine, using multiple simultaneous connections and opening \/ closing independently, so this <em>clearly<\/em> wasn&#8217;t an SSH connection problem.  Time to look somewhere else.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Except I was wrong.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By ruling out SSH I missed a critical, based troubleshooting step: connect to my new server via SFTP and issue a couple of commands. When I finally tried it, after beating around the bush for far too long, I had my &#8220;duh!&#8221; moment. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo and behold, SFTP failed.  I didn&#8217;t expect that could happen if SSH was fine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Of course, it failed with an inscrutable error in batch mode:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n$ echo &quot;ls \/&quot; | sftp -b - backup\nConnection closed.\nConnection closed\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Using the -v option was hardly more informative:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n$ echo &quot;ls \/&quot; | sftp -v -b - backup\nOpenSSH_9.0p1, OpenSSL 1.1.1q  5 Jul 2022\ndebug1: Reading configuration data ...\n&lt;snip&gt;\nsubsystem request failed on channel 0\nConnection closed.\nConnection closed\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Getting out of batch mode and trying to get a prompt gave me a little bit more information, but only just:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n$ sftp -v backup\nOpenSSH_9.0p1, OpenSSL 1.1.1q  5 Jul 2022\ndebug1: Reading configuration data ...\n&lt;snip&gt;\ndebug1: Sending subsystem: sftp\ndebug1: client_input_channel_req: channel 0 rtype exit-status reply 0\ndebug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0\ndebug1: channel 0: free: client-session, nchannels 1\nTransferred: sent 4528, received 4060 bytes, in 0.2 seconds\nBytes per second: sent 22612.3, received 20275.2\ndebug1: Exit status 127\ndebug1: compress outgoing: raw data 211, compressed 171, factor 0.81\ndebug1: compress incoming: raw data 918, compressed 764, factor 0.83\nConnection closed.  \nConnection closed\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Most disconcerting.  Fortunately, my Google-fu still had some juice today, and I learned something new from the search results.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The best clue was the exit status 127: <a href=\"https:\/\/serverfault.com\/questions\/770541\/can-connect-via-ssh-but-not-via-sftp-exit-status-127\">https:\/\/serverfault.com\/questions\/770541\/can-connect-via-ssh-but-not-via-sftp-exit-status-127<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SSH has something that appears to be a &#8220;legacy&#8221; option for configuring SFTP: the SFTP server subsystem.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Subsystem sftp &lt;subsystem&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You have three options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>internal-sftp<\/code>, which uses code built into SSH<\/li>\n\n\n\n<li>a user-defined external binary, e.g. <code>\/usr\/lib64\/misc\/sftp-server<\/code><\/li>\n\n\n\n<li>Omitting the option entirely, to choose no subsystem (effectively denying SFTP from your server)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/serverfault.com\/questions\/660160\/openssh-difference-between-internal-sftp-and-sftp-server\">https:\/\/serverfault.com\/questions\/660160\/openssh-difference-between-internal-sftp-and-sftp-server<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The base Raspberry Pi image I used included the 2nd option in the default sshd_config file, pointing to a non-existent binary.  Weird choice, but ok.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Subsystem      sftp    \/usr\/lib64\/misc\/sftp-server<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The internal subsystem is perfectly acceptable for many use-cases, and enabling it fixed my issue.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Subsystem      sftp    \/usr\/lib64\/misc\/sftp-server<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">SFTP now works. Testing show that Rex can distribute files to my Pi-server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One <em>could<\/em> argue that Rex should catch an error like this and present something friendlier than a stack trace, but one could also argue that people should know what they&#8217;re doing when they stand servers up.  SSH\/SFTP doesn&#8217;t emit a useful error here, either, and having a verbose error (&#8220;SFTP server not active&#8221; or some-such) would be a lot more helpful.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I use Rexify to manage my servers. (I&#8217;m learning to treat my servers like cattle, not pets.) I have it distributing standardized config files, running updates, and more. The Problem After adding a Raspberry Pi-based system to manage my backups, I was plagued with this error: The error didn&#8217;t make much sense, and wasn&#8217;t consistent. &hellip; <a href=\"https:\/\/blog.jonesling.us\/?p=3166\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Can&#8217;t call method &#8220;stat&#8221; on an undefined value&#8221;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[9],"tags":[754,389,788,790,789],"class_list":["post-3166","post","type-post","status-publish","format-standard","hentry","category-linux","tag-dad-saves-work-by-making-more-work","tag-perl","tag-rex","tag-sftp","tag-ssh"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p4o3FW-P4","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts\/3166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3166"}],"version-history":[{"count":16,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts\/3166\/revisions"}],"predecessor-version":[{"id":3185,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=\/wp\/v2\/posts\/3166\/revisions\/3185"}],"wp:attachment":[{"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jonesling.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}