Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

invoking umask command in perl

by austin43 (Acolyte)
on May 31, 2011 at 21:39 UTC ( #907541=perlquestion: print w/ replies, xml ) Need Help??
austin43 has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks, I have been trying to use backticks in a perl script to change the default system umask, but have run into some trouble. I tried:
`umask 0037`;
and it's not changing the default umask like I expected. I'm not sure how to invoke a specific shell for doing this, as I imagine that's the problem here. Any thoughts, ideas, or solutions are much appreciated. Thanks in advance!

Comment on invoking umask command in perl
Download Code
Re: invoking umask command in perl
by roboticus (Canon) on May 31, 2011 at 22:28 UTC

    austin43:

    As I understand it, umask is a built-in command in bash (I don't know about other shells). Not only that, but it only operates for the process that the shell is running in (I don't know about its descendents). So even if you do execute it, it will only affect the process that ends when the command returns to you.

    You probably want to use the perl umask function (see umask documentation under perldoc perlfunc).

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      I tried using the built in perl umask function but it doesn't change the default umask for root. The script is running with root priveleges, but either using backticks or the built in perl umask function doesn't change the default umask for root.

        austin43:

        Right. If you want to change the default umask for root, then edit the .bashrc for root (assuming a bash shell). Perl's umask simply sets the umask for the currently-running perl script, it doesn't attempt to change the umask setting for anything else. Even in bash, running umask won't set the default value for root, it only sets the value used in the current session. That's why .bashrc and .bash_profile exist--to allow you to set up the account defaults.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: invoking umask command in perl
by toolic (Chancellor) on May 31, 2011 at 23:46 UTC
      Last week I was trying to capture output instead of invoking a specific command. I can't use the same method as last week to actually change the umask. Could you shed some light as to how to do this?

        The problem you encountered today has the same source as the problem you encountered last time. You didn't learn the kind of problem, you just blindly took a solution. Also see umask for the Perl-builtin.

        Also note that you cannot affect the environment after your program has finished running.

Re: invoking umask command in perl
by ig (Vicar) on Jun 01, 2011 at 19:42 UTC
    it's not changing the default umask like I expected

    What is the result you expect?

    If you were doing it manually instead of using perl, what would you do? Have you done it successfully? Or is part of the problem that you don't know how to achieve your objective?

    If you answer these questions you may get better guidance.

      When I change it to 0037 in a terminal, I type:
      umask 0037
      This works successfully, as I check the umask afterward by typing:
      umask
      and it echoes:
      0037
      The result I expect is for the default umask to be changed to 0037. I simply don't know how to apply the same thing I do in a terminal to my perl script.

        This works successfully, as I check the umask afterward by typing

        Consider the process tree like an outline. Each node in the outline has a set of attributes. Each node is only able to modify its own attributes. When a child process is created, the attributes from the parent node are copied to the child node.

        umask is an attribute of the process. Your process is only able to modify the umask of itself. All children started by that process will then inherit the current umask at the time the child process is invoked. You cannot modify any process that is not the current process (ignore kernel hackery for this discussion).

        What you are considering behavior that "works" is the following:

        • Shell is using the internal directive to change its umask. From that moment on (at least until it is changed again), the shell is running with the new umask. If this were done with an external command, it would not work, since the external command would be on a different node in the outline.
        • Every child process started after that point inherits the current umask of the shell at the time the new process is started.

        What you are seeing in the terminal is consistent with the outline / attribute analogy. What you are seeing in the perl code is also consistent with the analogy. You are starting a child process (`umask...`), which is inheriting the current umask value of the perl process. Once the child process is complete, the parent continues on, not effected by what the child process did to change its umask attribute.

        When the perl process terminates, the parent process that started perl also does not care what perl did to its own umask attribute.

        Once you understand that a process is not effected by its children (outside of IPC means), a lot of things become clearer.

        --MidLifeXis

        The 'umask' function in your shell is a built-in function. It is executed by the shell itself and changes the setting of the shell itself. If it were a separate executable, then it would run in a sub-process of the shell and would affect itself but not the shell it was invoked from.

        If you write a Perl script and run it, it runs in a sub-process of your shell and cannot easily change the settings of your shell.

        If you want a Perl script that changes the setting of the shell you invoke it from, you have a challenge. It might be possible, if you have permissions to attach to and control that other process. For example, gdb can attach to a process and modify it in many ways. But I don't think you will find anything in Perl and possibly not in CPAN to do this.

        If you want a Perl script that changes the setting for itself and any processes it spawns, that's easy: use the umask function as Corion has suggested.

        Here is an example that shows how to invoke the bash 'umask' function from a Perl script, and how to set the umask of the perl script.

        use strict; use warnings; umask 0037; system('bash -c umask');

        If you run this and you have bash on your system you will see that the umask function in the bash process displays the umask you set in the script. If, after running this script you check the umask of your login shell, from which you invoked the Perl script (I'm making some assumptions here - let me know if they're not valid for you) then you will see that the umask of your login shell is not changed. This is expected. The general rule is that child processes do not change the setting of their parent processes.

        Your terminal example corresponds to this:
        perl -e 'print `bash -c "umask 0037 ; umask"`'
        And it works as well. What you are trying to do corresponds rather to this terminal session:
        umask 0037 exit umask
        which, clearly, does not do what you want.
Re: invoking umask command in perl
by ig (Vicar) on Jun 01, 2011 at 20:42 UTC
    `umask 0037`;

    The primary reason this fails is probably that there is no executable named umask on your system. I can't be certain there is non, as someone may have done something unusual on your system, but generally there is none.

    When I run such a command on my system, I get the following error: Can't exec "umask": No such file or directory at ./test.pl line 5.

    There is no umask executable because it would be difficult to write and contrary to the convention that child processes do not modify their parent process and would otherwise be useless except to display the current setting. It is a shell builtin function so that it can change the setting of the shell.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://907541]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (13)
As of 2014-10-21 15:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (105 votes), past polls