linux - Connect to the right serial port in Unix

06
2014-04
  • Atcold

    Background

    I'm trying to connect to a device using UART though a micro-USB cable and GNU screen from Ubuntu and OSX.

    On both Ubuntu and OSX I can get the most recent serial connection with the following command, which I have run just after having connected my device and turned it on.

    ls -t /dev/tty* | head -n 1
    

    On Ubuntu I get (this is actually the output of ll and -n 3 so I can see better what's shown)

    crw-rw---- 1 root dialout 166,  0 Jan 29 10:51 /dev/ttyACM0
    crw-rw-rw- 1 root tty       5,  0 Jan 29 10:14 /dev/tty
    crw-rw---- 1 root dialout   4, 68 Jan 21 16:19 /dev/ttyS4
    

    and the first item is correct (i.e. I can screen /dev/ttyACM0 115200).

    On Mac, instead, I get this

    crw--w----  1 atcold  tty     16,   4 29 Jan 10:56 /dev/ttys004
    crw-rw-rw-  1 root    wheel   19,  44 29 Jan 10:56 /dev/tty.usbmodemfd121
    crw--w----  1 atcold  tty     16,   6 28 Jan 16:21 /dev/ttys006
    

    and the first item is wrong (I cannot connect to it) whereas the working one is the second one (and I had to turn off and turn on my device twice, since the first time there was not any /dev/tty.usbmodemfd121 at all).

    Question

    My question is easy. How can I access automatically the correct serial connection? I'm trying to avoid to give too many troubles to the final user trying to sort this problem out automatically.

    Answer

    This is my final script :)

    read -p "Connect the switched off board, then press <Enter>" temp
    ls /dev/tty* > /tmp/old_tty
    read -p "Turn on the board and press <Enter>" temp
    ls /dev/tty* > /tmp/new_tty
    screen $(comm -13 /tmp/old_tty /tmp/new_tty) 115200
    
  • Answers
  • Alepac

    A solution could be to dectect the active serial connection before and after plugging the micro-usb, and then connect to the one present only after the micro-usb is plugged. This can be done for example with an sh script

    #!/bin/sh
    PATH_SUFFIX="/dev/tty"
    
    read -p "Be sure the mini usb adapter is unplugged then press ENTER" temp
    BEFORE=`ls -1 ${PATH_SUFFIX}* `
    read -p "Now plug device and then press ENTER" temp
    # sleep 2 seconds to be sure the filedevise is created
    sleep 2
    AFTER=`ls -1 ${PATH_SUFFIX}*`
    
    OLD_IFS=$IFS
    
    IFS='
    '
    
    for file in $AFTER ; do
        if case ${BEFORE} in *"${file}"*) false;; *) true;; esac; then
            FOUND=$file
        fi
    done
    
    IFS=$OLD_IFS
    
    #Now do whatever with FOUND device
    echo $FOUND
    
  • hardillb

    You might want to look at setting up a udev rule to create a symlink with a specific name for this serial device.

    Assuming you can identify the device by vendor or serial number.

    This should help:

    http://noctis.de/ramblings/linux/49-howto-fixed-name-for-a-udev-device.html


  • Related Question

    ubuntu - (Unix/Linux) How to execute different commands with same name?
  • Questioner

    I have a two seperate files on my computer,

    which execfile
    /usr/local/bin/
    /usr/bin/
    

    so, i have two files with the same name in two different directories. How can I specify exactly which command to run?

    Thanks.


  • Related Answers
  • Bertrand Marron

    you can specify the full path to the command when you run it type:

    /usr/bin/execfile
    

    or

    /usr/local/bin/execfile
    

    to run the exact file at that path

  • Dom De Felice

    When trying to execute a command foo, foo is searched in the directories specified by the PATH environment variable, in the same order as they are specified. If you want to avoid this, type the full path to the executable.

    Type this in a terminal:

    echo $PATH
    

    to see your actual PATH environment variable content.

    For example, if you want to always execute first executables inside /bin, make sure /bin comes first inside $PATH. You can specify PATH in the .profile file in your home directory. So for the example above, edit the file and put this line at the end:

    export PATH=/bin:$PATH

    This will work only for your user. If you want to specify $PATH in a system-wide fashion (it will work for all users except for those who change it in their .profile), add the same line above in the file /etc/profile (you will need root privileges.)

    Also remember that profile files are only parsed initially. This means that if you edit your personal .profile file, you will have to make your shell re-parse it. You can do this logging out and logging in again or otherwise typing:

    source ~/.profile

    For the system-wide change, type

    source /etc/profile

    This will make your current shell session re-parse the profile file. If you want your complete bootstrapped system to parse it again, I think you better restart your session.

    Also remember that this may change if you use a shell other than bash.

    You can find some interesting information inside the bash man page: http://linux.die.net/man/1/bash

    See section "Command Execution".

  • Dennis Williamson

    also check for that if they both belongs to same file - like it may be link

    ls -al /usr/bin
    ls -al /usr/local/bin
    

    and check whether they are linked together

    if they are linked then u can execute any no-difference, else you have to specify full path

  • Matthew Flaschen
    /usr/local/bin/execfile
    
    /usr/bin/execfile
    
  • fgm

    Write an alias in ~/.profile:

    alias execfile='/usr/local/bin/execfile'
    

    After the next login the right version will be chosen automatically. Start the other ones with the full path.