Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-52750

dir step creates a <dirname>@tmp directory at <dirname> level.

      In order to install some internal tools within /opt/tools through a Jenkins job, I have created a /opt/tools directory belonging to jenkins:jenkins and where user jenkins only (the user running the slave) has rwx rights.
      Trying something like :

      stages {
        steps('xyz') {
          dir('/opt/tools') {
             sh "pwd"
          }
        }
      }
      

      Fails with an exception ending with :

      java.nio.file.AccessDeniedException: /opt/tools@tmp
      	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
      	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
      	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
      	at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384)
      	at java.nio.file.Files.createDirectory(Files.java:674)
      	at java.nio.file.Files.createAndCheckIsDirectory(Files.java:781)
      	at java.nio.file.Files.createDirectories(Files.java:767)
      	at hudson.FilePath.mkdirs(FilePath.java:3098)
      	at hudson.FilePath.access$900(FilePath.java:209)
      	at hudson.FilePath$Mkdirs.invoke(FilePath.java:1216)
      	at hudson.FilePath$Mkdirs.invoke(FilePath.java:1212)
      	at hudson.FilePath$FileCallableWrapper.call(FilePath.java:2913)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:212)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:54)
      	at hudson.remoting.Request$2.run(Request.java:369)
      	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      	at java.lang.Thread.run(Thread.java:748)
      

      It appears that Jenkins tries to create a tools@tmp directory at the same level as tools. Yet, there is absolutely no reason for the tools root directory to be writable for any user.
      And as far as /opt is concerned here, for sure it must not be writable for anybody else than root.

      Additionnally, such @tmp directory is not removed once the build is achieved. Even though it seems that the directory is empty, I think that Jenkins should remove it to give back a clean environment.

       

          [JENKINS-52750] dir step creates a <dirname>@tmp directory at <dirname> level.

          Jesse Glick added a comment -

          Adjacent sh steps should be coalesced, and if possible their content externalized to a versioned script so that you are left with only a short one-line sh argument. Of course on occasion there is a reason for there to be intervening steps of other types.

          Jesse Glick added a comment - Adjacent sh steps should be coalesced, and if possible their content externalized to a versioned script so that you are left with only a short one-line sh argument. Of course on occasion there is a reason for there to be intervening steps of other types.

          jlpinardon added a comment -

          Hi all,

          The point is not only related to sh something, it is a more generic issue. Have I done the same with python, ruby or groovy step, I would have the same.
          The point is actually that when a dir() occurs, a @tmp folder is created behind the scene, and this is potentially a problem in some cases.

          jlpinardon added a comment - Hi all, The point is not only related to sh something, it is a more generic issue. Have I done the same with python, ruby or groovy step, I would have the same. The point is actually that when a dir() occurs, a @tmp folder is created behind the scene, and this is potentially a problem in some cases.

          Axel Heider added a comment -

          Any update here. I consider this a bug because it makes pipelines fail with strange errors and I have to add code that cleans up the mess. Also `dir()` is simply not relly usable then.

          Axel Heider added a comment - Any update here. I consider this a bug because it makes pipelines fail with strange errors and I have to add code that cleans up the mess. Also `dir()` is simply not relly usable then.

          Patrick added a comment -

          I've got the same problem with dir() in my Pipeline script. Is there any solution available yet?

          Patrick added a comment - I've got the same problem with dir() in my Pipeline script. Is there any solution available yet?

          Joel added a comment - - edited

          This is indeed a bug and I don't even manage to make the "cd " workaround work:

          The following pipeline:

          pipeline {
              agent {label 'ansible'}
              stages {
                  stage('playbook') {
                      steps {
                          sh '''
                              cd /git/it/ansible/infrastructure
                              pwd
                              ls -al
                              ./vault_pass
                              ansible-playbook --check docker.yml
                          '''
                      }
                  }
              }
          }
          

          yields that result:

          + cd /git/it/ansible/infrastructure
          + pwd
          /git/it/ansible/infrastructure
          + ls -al
          total 8
          drwxrwxrwx    1 root     root          4096 Nov 18 19:26 .
          drwxrwxrwx    1 root     root          4096 Nov 18 19:25 ..
          drwxrwxrwx    1 root     root          4096 Dec 14  2020 .git
          -rwxrwxrwx    1 root     root           234 Nov 20  2019 .gitignore
          -rwxrwxrwx    1 root     root           218 Nov 20  2019 .project
          -rwxrwxrwx    1 root     root          3354 Nov 20  2019 Vagrantfile
          -rwxrwxrwx    1 root     root           131 Nov 20  2019 all.yml
          -rwxrwxrwx    1 root     root           380 Nov 20  2019 ansible.cfg
          -rwxrwxrwx    1 root     root           720 Nov 20  2019 ansible.yml
          -rwxrwxrwx    1 root     root           126 Nov 20  2019 aptgetclean.yml
          -rwxrwxrwx    1 root     root            61 Nov 20  2019 common.yml
          -rwxrwxrwx    1 root     root           513 Nov 20  2019 docker.yml
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 files
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 group_vars
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 host_vars
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 inventories
          -rwxrwxrwx    1 root     root            94 Nov 20  2019 monitoring.yml
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 public_keys
          -rwxrwxrwx    1 root     root           227 Nov 20  2019 requirements.yml
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 roles
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 scripts
          drwxrwxrwx    1 root     root          4096 Nov 20  2019 templates
          -rwxrwxrwx    1 root     root          2172 Nov 20  2019 updater-rsync.yml
          -rwxrwxrwx    1 root     root            44 Nov 18 19:56 vault_pass
          -rwxrwxrwx    1 root     root            64 Nov 20  2019 weblate.yml
          + ./vault_pass
          /home/workspace/ansible@tmp/durable-ac15a4f4/script.sh: line 1: ./vault_pass: not found
          

          EDIT: this formatting language is difficult to handle....
           

          Joel added a comment - - edited This is indeed a bug and I don't even manage to make the "cd " workaround work: The following pipeline: pipeline { agent {label 'ansible' } stages { stage( 'playbook' ) { steps { sh ''' cd /git/it/ansible/infrastructure pwd ls -al ./vault_pass ansible-playbook --check docker.yml ''' } } } } yields that result: + cd /git/it/ansible/infrastructure + pwd /git/it/ansible/infrastructure + ls -al total 8 drwxrwxrwx 1 root root 4096 Nov 18 19:26 . drwxrwxrwx 1 root root 4096 Nov 18 19:25 .. drwxrwxrwx 1 root root 4096 Dec 14 2020 .git -rwxrwxrwx 1 root root 234 Nov 20 2019 .gitignore -rwxrwxrwx 1 root root 218 Nov 20 2019 .project -rwxrwxrwx 1 root root 3354 Nov 20 2019 Vagrantfile -rwxrwxrwx 1 root root 131 Nov 20 2019 all.yml -rwxrwxrwx 1 root root 380 Nov 20 2019 ansible.cfg -rwxrwxrwx 1 root root 720 Nov 20 2019 ansible.yml -rwxrwxrwx 1 root root 126 Nov 20 2019 aptgetclean.yml -rwxrwxrwx 1 root root 61 Nov 20 2019 common.yml -rwxrwxrwx 1 root root 513 Nov 20 2019 docker.yml drwxrwxrwx 1 root root 4096 Nov 20 2019 files drwxrwxrwx 1 root root 4096 Nov 20 2019 group_vars drwxrwxrwx 1 root root 4096 Nov 20 2019 host_vars drwxrwxrwx 1 root root 4096 Nov 20 2019 inventories -rwxrwxrwx 1 root root 94 Nov 20 2019 monitoring.yml drwxrwxrwx 1 root root 4096 Nov 20 2019 public_keys -rwxrwxrwx 1 root root 227 Nov 20 2019 requirements.yml drwxrwxrwx 1 root root 4096 Nov 20 2019 roles drwxrwxrwx 1 root root 4096 Nov 20 2019 scripts drwxrwxrwx 1 root root 4096 Nov 20 2019 templates -rwxrwxrwx 1 root root 2172 Nov 20 2019 updater-rsync.yml -rwxrwxrwx 1 root root 44 Nov 18 19:56 vault_pass -rwxrwxrwx 1 root root 64 Nov 20 2019 weblate.yml + ./vault_pass /home/workspace/ansible@tmp/durable-ac15a4f4/script.sh: line 1: ./vault_pass: not found EDIT: this formatting language is difficult to handle....  

          Hatter added a comment -

          I'm surprised to see this issue is still not fixed yet in 2023...

          Hatter added a comment - I'm surprised to see this issue is still not fixed yet in 2023...

          Harikishen Hosamana added a comment - - edited

          I don't think the AccessDeniedException is unexpected.
          dir seems to expect a relative path as argument.

           

          Ref: https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#dir-change-current-directory

          Harikishen Hosamana added a comment - - edited I don't think the AccessDeniedException is unexpected. dir seems to expect a relative path as argument.   Ref: https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#dir-change-current-directory

          Joel added a comment -

          I fail to see how AccessDeniedException is to be expected.

          It is at least not mentioned in the documentation, let alone be intuitive that whenever we change directory a @tmp folder will be generated as sibling (and therefore the parent must be writable). 

          What I expected, is that when I use the dir directive to change folder, I would actually be in that folder.

          Joel added a comment - I fail to see how AccessDeniedException is to be expected. It is at least not mentioned in the documentation, let alone be intuitive that whenever we change directory a @tmp folder will be generated as sibling (and therefore the parent must be writable).  What I expected, is that when I use the dir directive to change folder, I would actually be in that folder.

          We ran into this very same issue some days ago. Actually I am puzzled we haven't had this trouble earlier already.

          According to my experiments there is a (subtile) difference on wether the directory does exist on checkout(seems working) or wether it was created during the build in another step (causing troubles).

          Any suggestions for workarounds available?

          Peter Niederlag added a comment - We ran into this very same issue some days ago. Actually I am puzzled we haven't had this trouble earlier already. According to my experiments there is a (subtile) difference on wether the directory does exist on checkout(seems working) or wether it was created during the build in another step (causing troubles). Any suggestions for workarounds available?

          yoni added a comment -

          Could anyone suggest a possible workaround for this issue?

          yoni added a comment - Could anyone suggest a possible workaround for this issue?

            Unassigned Unassigned
            jlpinardon jlpinardon
            Votes:
            16 Vote for this issue
            Watchers:
            22 Start watching this issue

              Created:
              Updated: