I occasionally need to customise MATLAB scripts depending on the machine it is being run on. I usually use the following command to grab the computer name:
char(getHostName(java.net.InetAddress.getLocalHost)
This returns a computer name in most cases. However, my laptop (a MacBook) varies depending on which network I am connected to.
Is there a way of retrieving some sort of unique identifier about the computer that does not change depending on the network it is connected to?
Update: I forgot to mention that I am looking for a solution that is OS independent. I need to find a command that works whether on Mac, PC or Linux.
A good identifier that is independent of network is the MAC Address (nothing to do with macbook). Every computer has a unique MAC Address. You can get it with this command on MATLAB:
system('ifconfig en0 | grep ether')
You will get something like that on the output:
ether 80:e6:50:28:76:d0
you can use the Hardware addresses of the computer’s network cards, as suggested here, extracting it with the following Matlab code:
not_win=true;
switch computer('arch')
case {'maci','maci64'}
[~,mac_add]=system('ifconfig |grep ether | grep -o -E "([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}"');
case {'glnx86','glnxa64'}
[~,mac_add]=system('ifconfig | grep HWaddr | grep -o -E "([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}"');
case {'win32','win64'}
not_win=false;
sid = '';
ni = java.net.NetworkInterface.getNetworkInterfaces;
while ni.hasMoreElements
addr = ni.nextElement.getHardwareAddress;
if ~isempty(addr)
sid = [sid, '.', sprintf('%.2X', typecast(addr, 'uint8'))];
end
end
otherwise, error('Unknown architecture')
end
if(not_win)
mac_add=regexprep(mac_add,'\r\n|\n|\r','.');
sid=upper(strrep(mac_add(1:end-1),':',''));
end
The sid variable contains the unique identifier you are looking for.
You have to detect the architecture of the machine, because java.net.NetworkInterface.getNetworkInterfaces does not properly work on Unix, returning only running interfaces; so you have to gathered mac addresses parsing the results of ifconfig (take a look here for some examples).
Pay attention! On Mac, if you start a Virtual Machine, fake network interfaces could be added, so the sid may change.
Related
There is a server that starts and listens to a SOCK_SEQPACKET. I think a SOCK_SEQPACKET has a name, say, #Foo. It's per user, so initiated by each Linux user account, and there is only one service per user.
The goal is to make an external tool that forcefully kill the service when something goes wrong. The language is C++.
When I have to kill that service, I use netstat:
$ netstat -lnp | egrep Foo
I would not like to have a dependency on the net-tools package, though. I would like to do this with minimal dependencies on external tools and/or even libraries.
I've tried Google search, and could not find how. I guess I could perhaps read netstat source code to see how they do; I would like to defer that to the last resort, though. I have learned how I could kill the service, using netstat, which gives me dependency on net-tools. The service somehow runs as /proc/self or so. I could visit every process ID in /proc, and see if that looks like the service: see the executable name, etc. However, that is not necessarily sufficient indication to narrow down to that one single process, which uses the #Foo SOCK_SEQPACKET. Now, as non-expert in socket/network programming, I am running out of ideas about how I should proceed.
As #user253751 says, that's not actually a socket type but more of a socket behavior type. As they suggested, it is probably a unix domain socket. Given the '#' sign in it, it is almost certainly using the unix domain socket's "abstract" namespace (which means the socket doesn't have an endpoint directly visible in the filesystem). At the system call level, such endpoints are created with a null byte as the first character (the # is commonly substituted in command line utilities or wherever the socket is surfaced to user space for user convenience). See the unix(7) man page for more details.
Since the socket doesn't appear in the filesystem anywhere, it can be difficult to find the association of process to socket. One way you can find that is through use of the lsof utility -- but that is probably little improvement over the netstat utility.
It appears that the abstract namespace sockets do show up in the /proc/net/unix pseudo-file. In association with that, there is an inode column (second to the last). In conjunction with looking at each process's /proc/<pid>/fd directory, I think you can make the association.
For example, I created a small python program that creates a Unix domain SOCK_SEQPACKET socket and binds it to '#Foo'. That program is here:
import socket, time
sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
sock.bind('\0Foo') # Note the \0 for the initial null byte
time.sleep(10000) # Just hang around while we do other stuff
In a separate terminal window:
gh $ grep '#Foo' /proc/net/unix
0000000000000000: 00000002 00000000 00000000 0005 01 7733102 #Foo
gh $ sudo bash -c 'for proc in /proc/[0-9]*; do ls -l $proc/fd | grep 7733102 && echo $proc; done'
lrwx------ 1 gh gh 64 Feb 2 17:13 3 -> socket:[7733102]
/proc/339264
gh $ ps -fp 339264
UID PID PPID C STIME TTY TIME CMD
gh 339264 22444 0 17:11 pts/3 00:00:00 python3
gh $ ls -l /proc/339264/fd
total 0
lrwx------ 1 gh gh 64 Feb 2 17:13 0 -> /dev/pts/3
lrwx------ 1 gh gh 64 Feb 2 17:13 1 -> /dev/pts/3
lrwx------ 1 gh gh 64 Feb 2 17:13 2 -> /dev/pts/3
lrwx------ 1 gh gh 64 Feb 2 17:13 3 -> 'socket:[7733102]'
Explaining:
First, we do a grep on /proc/net/unix for the '#Foo' socket. That gives us the inode number 7733102 (second to last column). The inode number is unique to every socket on the system.
Next, as root, we do an ls -l /proc/<pid>/fd for each process on the system and grep for the inode number we found in the previous step. When found, we printed out the /proc/<pid> entry. (On linux, that pseudo-directory shows a symlink to a representation of what each file descriptor open in the process is. For sockets, that representation is always socket:[<inode>].) Here we found the process ID is 339264.
The remaining two steps are just confirming that that is in fact, our python process, and you can see its four open files (the first three [stdin, stdout, stderr] all pointing to its terminal's pseudo-tty, the fourth to the socket).
To make this into a more foolproof program, you'd need to account for the fact that the inode number you found in step 1 could be a substring of some other socket's inode number but that is left as an exercise for the reader. :)
What module would you recommend to get a disk name on Linux? I've done some search on CPAN but all modules I've found are too old. In Bash I can use something like:
disk_name=$(df |grep -w '/'|awk '{print $1}'|cut -d/ -f3)
echo $disk_name
sda6
Please help me to understand how to do same in Perl.
Thanks.
The "proper" way to list mounted disks on Linux is through the getmntent() system call, which can be accessed from Perl using the Quota module:
use Quota;
Quota::setmntent();
while (my ($dev, $path, $type, $opts) = Quota::getmntent()) {
print "The root device is $dev.\n" if $path eq "/";
}
Quota::endmntent();
As a bonus, using the Quota module to list device mount points should be fairly portable to other Unixish systems, which parsing various system files or the output of df may not be. Unfortunately, this seemingly basic module is not included in the standard Perl distribution, so you have to get it from CPAN (or from your distro's package repository — for example, Debian / Ubuntu have the libquota-perl package).
Ps. Simply splitting the device name on / and taking the third element (as your cut command does) is not a safe way to turn, say, /dev/sdb1 into sdb1. Some issues with it are that:
Not all block devices have to live under /dev — it's really just a convention.
Even if the device file is under /dev, it might be in a subdirectory of it. For example, my root filesystem is on the device /dev/disk/by-uuid/627f8512-f037-4c6c-9892-6130090c0e0f.
Sometimes, the device name might not even be an actual filesystem path: for example, virtual or in-memory filesystems such as tmpfs are often mounted with the device name none, but it's possible to use any device name with them.
If you do want to get rid of the /dev/ part, I'd suggest a conservative approach using a regexp, for example like this:
if ($dev =~ m(^/dev/(.*)$)s) {
print "The directory $path is mounted from device $1 under /dev.\n";
} else {
print "The directory $path is not mounted from a device under /dev.\n"
}
What you're describing is not the disk name but the device name of the block device representing the partition mounted at root (/). On a regular computer it would normally be something like /dev/sdXN or /dev/hdXN with X being the disk number (primary hard drive is usually A, secondary is B, etc.) and N is the partition number on that device.
Provided you're always running on a unix system, you can try reading /etc/mtab file, which lists all mounted partitions, or the special file /proc/mounts, which pretty much does the same. You'll need to parse it afterwards to find the one you need and get the device name from it.
Alternatively, you can just run df as a process and get its input into perl, something like
open(DF, "df|");
#mount_points = <DF>;
close(DF);
and then iterate over the data to find what you need. I'm not aware of any modules of the top of my head that would do the job for you, but the code seems pretty simple to me anyway.
P.S. Note that Max OS X, while being a derivative of BSD, doesn't have the same file structure and therefore this approach wouldn't work. On Mac OS X, you can read file /etc/fstab.hd, which contains similar info but in a slightly different format.
One way to do just what you are doing in the question
df / | perl -ne 'm"^/\w+/(\w+)";print "$1\n" if defined $1;'
but using a CPAN library to do it is probably better.
im using procmail to forward emails to different folders in my Maildir.
I use these two lines to get the FROM and TO from the mail, which works pretty fine.
FROM=`formail -x"From:"`
TO=`formail -x"To:"`
These two commands return the whole line without the From: and To: prefix.
So i get something like:
Firstname Lastname <firstname.lastname#mail-domain.com>
Now i want to extract the email between < and >.
For this i pipe the variable FROM and TO grepping it like this.
FROM_PARSED=`echo $FROM | grep -o '[[:alnum:]+\.\_\-]*#[[:alnum:]+\.\_\-]*'`
TO_PARSED=`echo $TO | grep -o '[[:alnum:]+\.\_\-]*#[[:alnum:]+\.\_\-]*'`
But when i print FROM_PARSED into the procmail log by using LOG=FROM_PARSED, i get an empty string in FROM_PARSED and TO_PARSED.
But if i run these commands on my console, all works fine. I tried many other grepping methods, using grep, egrep, sed and even cut (cutting < and >). All working on console, but i use it in procmail it just returns nothing.
Is it possible that procmail is not allowed to use grep and sed commands? Something like a chroot?
I dont get any error logs in my procmail log. I just want to extract the valid email address from the FROM and TO line. Extracting with formail works, but parsing it with grep or sed fails, even if expression is correct.
Could somebody help? Maybe i need to setup procmail somehow.
Strange.
I added this to the users .procmailrc file
SHELL=/bin/bash
The users shell was set to /bin/false, which is correct because its a mail user, no ssh access at all.
You should properly quote "$FROM" and "$TO".
You will also need to prefix grep with LC_ALL=POSIX to ensure [:alnum:] will actually match the 26 well-known characters + 10 digits of the English alphabet.
You already solved this, but to answer your actual question, it is possible to run procmail in a chroot, but this is certainly not done by Procmail itself. Sendmail used to come with something called the Sendmail Restricted Shell (originally called rsh but renamed to remsh) which allowed system administrators to chroot the delivery process. But to summarize, this is a feature of the MTA, not of Procmail.
While creating a file, you provide the name of a file to operating system and
it creates file and returns you the handle.
I am curious to know how it is created.
Does the operating system do some kind of hashing on file name to create a unique file handle
or does it increase count of created files and return it as a file handle?
No, it's an index into an array inside the OS kernel, unique to that one process. File handles are usually just small integers.
File handles are only unique within one process at a given time. On Linux I think that it is a simple counter that is incremented. I think that Windows returns the memory address to an information block about the file (the information block's structure is internal to the operating system, so it's not possible to deal with it directly).
The file handle (file descriptor) is just a number which is unique for that particular process. For instance, standard input, output and error has fds (0, 1, 2). In linux you can check the process' file descriptor in /proc/PID/fd where PID is process id.
Here is an example:
$ pidof executable
4711
$ ls -l /proc/4711/fd
...
$ # Use 'lsof' to show file descriptor opened by this process:
$ lsof -p 4711
...
Is there a way to check if my domain is setup correctly on the nameservers? Ideally I'd like to run a command from command line, alternatively can use a third party tool.
for example, I'm trying to register a domain that's to be hosted on godaddy.com. I have set up the domain and can see it in my DNS list. The servers that are supposed to be setup are ns51.domaincontrol.com and ns52.domaincontrol.com, however my registration is bouncing saying that there are "No Nameservers found for {my new domain}".
I think this is the shortest and quickest command to list your nameservers:
host -t ns yourdomain.com
If you're on a Mac or Unix machine you can do the following from command line:
whois site.com
Toward the end it should give you a list of DNS servers.
You can filter the list, showing only the Name Server information, with:
whois site.com | grep "Name S"
Note that www.site.com and site.com are two different end points and you need to set up appropriately for both of them.
Zonecheck is a free software and can be run from the command line:
% zonecheck stackoverflow.com
ZONE : stackoverflow.com.
NS <= : ns51.domaincontrol.com. [216.69.185.26]
NS : ns52.domaincontrol.com. [208.109.255.26]
_______________
,---------------.|
~~~~ | warning || ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`---------------'
w> Nameservers are all part of the same AS
| Adv: ZoneCheck
| To avoid loosing all connectivity with the authoritative DNS in case
| of a routing problem inside your Autonomous System, it is advised to
| host the DNS on different AS.
`----- -- -- - - -
: All the nameservers are part of the same Autonomous System (AS number
: 26496), try to have some of them hosted on another AS.
`..... .. .. . . .
=> generic
==> SUCCESS (but 1 warning(s))
There is a built-in command line for that: nslookup
Submit it, then write set type=ANY and press enter. After which specify desired domain and you'll get what you are looking for. Alternatively, enter ? and see more options for the nslookup command line.
PS: while this answer comes with a delay, hope it to be useful for others who want to check nameserver/DNS setup from command line.
nm-tool run from the command line will give you much information, not the least of which is the DNS servers you're using. You may have to install this, but many distros have it included.