How to execute lua bytecode genrated by luac on linux - linux

I have a simple lua source code called hello.lua
print('Hello Lua')
I complied this file to bytecode on a RedHat Linux machine , using Lua5.3.4 as follows:
luac -o hello.luac hello.lua
chmod +x hello.luac
./hello.luac
bash: ./hello.luac: cannot execute binary file
The architecture should be fine I guess. I cant figure what is wrong.

Precompiled Lua programs are run exactly the same way as source:
lua hello.luac

The shebang is removed by luac even if the lua source file has it. In some case when it's necessary to run the compiled binary without any parameter, e.g. CGI, you can add the shebang manually at the top of the luac file:
luac -o hello.luac hello.lua
echo '#!/usr/bin/env lua' > shebang
cat shebang hello.luac > hello.luac2
mv hello.luac2 hello.luac
chmod +x hello.luac
./hello.luac

As #lhf states in his answer Lua byte code is executed using the Lua interpreter, and as the manual suggests:
To allow the use of Lua as a script interpreter in Unix systems, the standalone interpreter skips the first line of a chunk if it starts with #. Therefore, Lua scripts can be made into executable programs by using chmod +x and the #! form.
Add a shebang as the first line of your script:
#!/usr/bin/env lua
print('Hello Lua')

Related

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

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.

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) "$#"

How to change Example.bat to Example.pl?

I have read other threads enter link description herethat discuss .bat to L/unix conversions, but none has been satisfactory. I have also tried a lot of hack type approach in writing my own scripts.
I have the following example.bat script that is representative of the kind of script I want to run on unix.
Code:
echo "Example.bat"
perl script1 param.in newParam.in
perl script2 newParam.in stuff.D2D stuff.D2C
program.exe stuff.D2C
perl script3 stuff.DIS results.out
My problem is I don't know how to handle the perl and program.exe in the unix bash shell. I have tried putting them in a system(), but that did not work. Can someone please help me?
Thank you!
Provided that you have an executable file named program.exe somewhere in your $PATH (which you well might — Unix executables don't have to end in .exe, but nothing says they can't), the code you've pasted is a valid shell script. If you save it in a file named, say, example.bat, you can run it by typing
sh example.bat
into the shell prompt.
Of course, Unix shell scripts are usually given the suffix .sh — or no suffix at all — rather than .bat. Also, if you want your script to be executable directly, by typing just
example.sh
rather than sh example.sh, you need to do three things:
Start the script with a "shebang" line: a line that begins with #! and the full path to the shell interpreter you want to use to run it (e.g. /bin/sh for the basic Bourne shell), like this:
#!/bin/sh
echo "This is a shell script."
# ... more commands here ...
Mark your script as executable using the chmod command, e.g.
chmod a+rx example.sh
Put your script somewhere along your $PATH. On Unix, the default path will not normally contain the current directory ., so you can't execute programs from the current directory just by typing their name. You can, however, run them by specifying an explicit path, e.g.
./example.sh # runs example.sh from the current directory
To find out what your $PATH is, just type echo $PATH into the shell.

perl + perl script location under /etc/rc3.d with diff results

I need advice about the following:
option 1
I run the script /usr/local/bbp/api/bbpinstaller.pl from /var/tmp directory in my Linux machine and there are no problem
option 2
I create new script - script.pl under /var/tmp
and then I create link from /var/tmp/script.pl to /etc/rc3.d/S99script.pl ( by ln -s )
so S99script.pl is link to /var/tmp/script.pl
and script.pl execute the /usr/local/bbp/api/bbpinstaller.pl
more /etc/rc3.d/script.pl
#!/bin/bash
/usr/local/bbp/api/bbpinstaller.pl
.
.
.
my problem :
when the script bbpinstaller.pl run after reboot from /etc/rc3.d/S99script.pl then I get the following errors ( /usr/local/bbp/api/bbpinstaller.pl run from S99script.pl )
Can't locate Term/ReadKey.pm in #INC (#INC contains: /etc/bbp/shared /usr/perl5/5.8.4/lib/sun4-solaris- 64int /usr/perl5/5.8.4/lib /usr/perl5/site_perl/5.8.4/sun4-
solaris- 64int /usr/perl5/site_perl/5.8.4 /usr/perl5/site_perl /usr/perl5/vendor_perl/5.8.4/sun4- solaris-64int /usr/perl5/vendor_perl/5.8.4 /usr/perl5/vendor_perl
. ) at /usr/local/bbp/api/bbpinstaller.pl line 25.
BEGIN failed--compilation aborted at /usr/local/bbp/api/bbpinstaller.pl line 25.
in /usr/local/bbp/api/bbpinstaller.pl script , I have the following perl modules:
#################################
# Modules imported
#################################
use Config;
use Getopt::Long;
use File::Find;
use English;
use Sys::Hostname;
$File::Find::dont_use_nlink=1;
use lib "/etc/bbp/shared";
use Term::ReadKey qw(GetTerminalSize);
use Cwd 'abs_path';
require "bbp_globals.pl";
require "bbp_functions.pl";
the PATH of the file ReadKey.pm
/usr/local/lib/perl5/site_perl/5.8.7/sun4-solaris-thread-multi/Term/ReadKey.pm
please help me to understand . what the problem here ??? ( I not have allot experience with Perl )
/usr/local/ is used by local installs (i.e. it wasn't provided by the OS vendor). Then your shell is setup to run ($PATH) /usr/local/bin/perl (5.8.7) rather than /usr/local/bin/perl (5.8.4).
However the init scripts don't run with your shell settings - they use the system settings, which won't have /usr/local/bin in them - so they will use the OS provided perl - /usr/bin/perl which doesn't have this library (Term::ReadKey) installed.
(The .pl extension is normally for perl programs - I'd use .sh for bash/shell scripts)
When you run a script directly (that is, not specifying an interpreter first on the command-line), the kernel uses the hash-bang line (the first line) to work out which program to execute to interpret the script.
e.g. your shell script /etc/rc3.d/script.pl has a hash bang line of "#!/bin/bash", telling it to execute with /bin/bash.
/usr/local/bbp/api/bbpinstaller.pl will have a hash-bang line at its start, possibly something like: #!/usr/bin/env perl
This tells the kernel/shell to look at the PATH variable to find an interpreter; the same way it would find perl if you typed it on the command-line.
In order to fix your problem, either:
Install Term/ReadKey into the system perl.
Set your PATH in you shell script as MichaelN suggests.
Call the explicit perl instead of letting the kernel decide, as MichaelN also suggests.
Recode /usr/local/bbp/api/bbpinstaller.pl to not need Term/ReadKey
By default the os perl is /usr/bin/perl which has all its modules in /usr/perl5/site_perl/5.8.4 /usr/perl5/site_perl. Since running the script via rc3 uses root's standard path and standard lib, it won't find your custom perl in /usr/local/bin and thus won't find your site-lib in /usr/local/lib. So you need to modify your calling script "/etc/rc3.d/script.pl" which is a bash script (should probably be call script.sh but that's symantics) to include /usr/local/bin in the path, ie: export PATH=/usr/local/bin:${PATH}. That'll pre-append the /usr/local/bin to the front of the PATH and then your perl in /usr/local/bin will be called instead of /usr/bin/perl. So change the script.pl to:
#!/bin/bash
export PATH=/usr/local/bin:${PATH}
/usr/local/bbp/api/bbpinstaller.pl
or call your script with your perl.
#!/bin/bash
/usr/local/bin/perl /usr/local/bbp/api/bbpinstaller.pl
I'm totally keying off the work Douglas did in analyzing your issue, in order to provide the fix you asked for.
I would either:
In the RC shell script, set your PATH to run the right version of perl, and then call your Perl script.
Change the "shebang" line in your Perl script to use the right version of Perl.
Hope one of those helps!

Resources