Why i can excute a newly created file which is not executable? - linux

In Ubuntu, The default umask on Ubuntu is 022 which means that newly created files are readable by everyone, but only writable by the owner, nobody can excute it.
In this case, i create a new file :
touch test.rb # Its content is: puts "hello world"
ls -l demo.rb # -rw-r--r--
Then i excute test.rb :
ruby test.rb # output: "hello world"
Since the owner of the file does not have the "x" permission , then why I can successfully run the file ? or I have missed some knowledge about it ?

You are not executing the file as a binary. You are executing ruby binary with argument test.rb and it interprets the Ruby script. Therefore, only ruby binary needs execution privilage and not the script itself.
You can check the privileges of the binary by running stat (which ruby).
On the other hand if you place
#!/usr/bin/ruby
on the top of your script and make it executable with chmod a+x test.rb you could then make Linux run it. The binfmt module of the kernel will check search for #! (called shebang) in the file and run the interpreter for you.
You can find this shebang in lot of the shell scripts. Nowadays it is common to put #!/usr/bin/env ruby or #!/usr/bin/env python in order to use interpreter binary in other location that is available on PATH variable like /usr/local/bin/ruby. Again env is just another binary program. It will run its argument as a program. The kernel will pass script as the parameter which will result in command /usr/bin/env ruby test.rb.

Grzegorz Żur is right.
you can modify your test.rb like this:
#!/usr/bin/env ruby
puts 'hello world'
and then you excute it with .:
$ ./test.rb
you will see Permission denied.

Related

Why bin/www file doesn't have extension in express-generator?

I always have this doubt and I don't know why the file inside the bin folder which create a simple http server doesn't have a .js extension.
Is there a reason behind this?
It's tradition on unix that executables don't have extension.
For example, on Linux and MacOS to list a directory you type:
ls
you don't type
ls.exe
Another example, to launch the Dropbox service on Linux you can type
dropbox
you don't type
dropbox.py
even though dropbox is just a text file containing Python code.
Unix (and also bash terminal on Windows) have a feature where if a file is marked as executable (using the chmod command) and the first line contains:
#!
.. then the shell (the program controlling the command line) will remove the first two characters (#!) and execute the rest of that first line. This is often called the shbang line (sh = shell, ! = bang).
Therefore, if you want to develop a command-line program in node.js all you need to do is start the file with #! /usr/bin/env node:
#! /usr/bin/env node
// ^
// |
// the 'env' command will find the correct install path of node
console.log('hello world');
Then use chmod to make the file executable:
chmod +x my-script.js
Of course, creating a program that ends in .js does not look "professional". For example you don't type gulp.js when you run gulp and you don't type npm.js when you run npm. So people follow tradition and make their executable scripts have no extension - it makes it harder for people to realise that you didn't write the program in C or assembly language.
Because www file is executable.
Open a console, go to the bin folder, and type ./www . The server will run.

Why does a bash script require an execute bit if a windows batch script can just be executed?

Yesterday I ran into the git execute bit bash script quirk - the one that requires:
git update-index --add --chmod=+x scriptname.sh
and it seemed strange to me that it was even possible to get stuck in this situation. (Ie having created a script file that you don't have permission to run).
If I have created a shell script - surely I can run it under the permissions of the shell execute permissions. Why would it need it's own execute permission bit?
My question is: Why does a bash script require an execute bit if a windows batch script can just be executed?
To run a script you have two options in unix like systems. First Option is to use a direct interpreter call with the script as parameter.
# run a bash script
bash test.sh
# run a python scripts
python test.py
The second option is mark your file as executable, with the execute bit and after a call like this ...
# sample bash
./test.sh
# sample python
./test.py
... your system tries to find the right interpreter for you. For this the first line 'shebang' of the script is used.
Bash example:
#!/bin/bash
# points to the installed bash interpreter - bash example
Python example:
#!/usr/bin/python
# points to the installed python interpreter
To your question windows only use the file extension to detect a executable file.
Well, Linux is not Windows. Linux/Unix file systems support the executable bit to distinguish executable from pure data files, and to control exec permissions for user|group|others. You can still run the script if you prefix it with the name of the shell/binary you want to start it with, but if you want to do ./scriptname.sh or execute it from the path it needs to be flagged as executable for you as the onwer|a group member|some other user, and for scripts usually the shebang in the first line that defines the interpreter to start the script with: #!/bin/bash.

Anyway to change the default exec call length?

I have a bash script and will have the first line start with # and followed by the command to execute the script, and it seems the limitation is 80 characters due to the exec call has such limitation, is there anyway to change that ? because sometimes my path will be very long.
Update.
My case is that I use virtualenv to generate a clean python environment. And in this environment, there's one executable file called pip, the shebang line is python executable path and sometimes this path will be very long, e.g.
#!/Users/myname/github/myproject/virtualenv_python3.4/bin/python3.4
If you don't want to modify your path to include the directory in which the executable, you can create a simple wrapper:
#!/bin/bash
/Users/myname/github/myproject/virtualenv_python3.4/bin/python3.4 <(cat <<"EOF"
# Python script goes here
EOF) "$#"

Can't run a script

I tried to create a script in linux, on a Synology server over SSH
so I wrote a file test.sh
#!/bin/bash
echo "this is a test"
I saved the file.
after that I did
chmod 755 test.sh
the I did
./test.sh
then i got this error
-ash "./test.sh" is not found
the file was created in
/root
I don't understand
Your shell (ash?) is trying to execute your script and is getting an ENOENT (no such file or directory) error code back. This can refer to the script itself, but in this case it refers to the interpreter named in the #! line.
That is, /bin/bash does not exist and that's why the script couldn't be started.
Workaround: Install bash or (if you don't need any bash specific features) change the first line to #!/bin/sh.
This is one of the quirks with hash bang programs. If the interpreter is not found (i.e. the program interpreting the script), you don't get a completely useful error like /bin/bash: no such file, but a completely useless and misleading test.sh: not found.
If this isn't in the Unix Hater's Handbook, it should be. :-)
You can either use #!/bin/sh or #!/path/to/bash or #!/usr/bin/env bash (which searches PATH for bash).

How to set a program to run in Linux terminal only with program name

I'm new to Linux and I wonder there are many programs we can use only program name to start it in Linux terminal, like gedit,vi,firefox instead of providing the all program's path,I like to run my own programs like this in terminal only typing program name, programs I like to run are written in Java and Python (.jar, .pyc, .py and .class)
I like to know how to do it with step by step
You can write whatever program/script you have to behave as a command. Let's say your executable script/program is named as my_script and is placed in /path/to/my_script.
Be sure that the script is executable. If not,then please do
chmod +x /path/to/my_script
Then, place a symlink to this location in /usr/local/bin as
sudo ln -s /path/to/my_script /usr/local/bin
You can add the symlink to any of the paths mentioned in $PATH.
That's it and enjoy your program.
The other answers all involve creating a symlink in a directory that is already listed in the system PATH, but I think it is more unixy to add needed directories to your PATH.
If your script is located at $HOME/bin/myscript and you have already made sure that it is executable then you can run
export PATH=$HOME/bin:$PATH
to run it without giving the full path. And you can add that same line to your .bashrc file in your home directory to have it preloaded whenever you start your shell. This approach does not require that the user has permission to create symlinks in system directories.
If you have an executable binary file in your home folder (let's say for example sublime_text) you must give it execute permision and call it with its relative path
chmod +x sublime_text
./sublime_text
If you made a symlink to it in /usr/bin (or other folders included in your PATH), you would be able to call it by its name
sudo ln -s ~/sublime_text /usr/bin/sublime_text
sublime_text
In your case, you aren't dealing with binary files, but with scripts meant to be interpreted. For this you must prepend a shebang telling linux what's the binary meant to execute the script. If it was, for example, a python script ~/hello.py, these could be the contents of the script:
#!/usr/bin/python
print "Hello, World!"
Where the first line tells linux to use the python binary to execute the script.
From then on, you can do:
chmod +x hello.py
sudo ln -s ~/hello.py /usr/bin/hello
hello
And it will echo "Hello World" to the console.

Resources