มีวิธีการสร้างลิงก์สัญลักษณ์จากโฟลเดอร์บนเครื่อง Windows ไปยังไดเรกทอรีบน Linux หรือไม่?


1

ฉันมีโปรแกรมที่ทำงานบน Windows VirtualBox VM และเก็บข้อมูลไว้ในโฟลเดอร์เฉพาะ ฉันอยากจะทำอะไรบางอย่างเช่นลิงก์สัญลักษณ์จากโฟลเดอร์นี้ไปยังไดเรกทอรีบนเซิร์ฟเวอร์ Linux แต่ฉันไม่สามารถหาวิธีแก้ปัญหาที่ใช้งานได้ ฉันลองแมปโครงสร้างโฟลเดอร์ Linux กับตัวอักษรชื่อไดรฟ์แล้วสร้าง Junction จากโฟลเดอร์ Windows 'ดั้งเดิม' ไปยังโครงสร้างที่แมปกับตัวอักษรชื่อไดรฟ์ แต่ Windows จะไม่ให้ฉันทำลิงค์ให้เสร็จ ฉันพยายามเชื่อมต่อไดเรกทอรี Linux โดยใช้ SFTP และไม่ได้ผลเช่นกัน


ดังนั้นในหน้าต่าง vbox คุณลองทำสิ่งที่ต้องการmklink /d c:\local_folder \\192.168.1.2\linux_share
Yorik

คำตอบ:


1

นี่คือสิ่งที่ฉันทำ

ก่อนอื่นฉันติดตั้ง SAMBA บนกล่อง Linux และแบ่งปันไดรฟ์ที่ฉันต้องการใช้ (นี่เป็นหัวข้อที่สมบูรณ์ยิ่งขึ้น แต่คุณสามารถหาคำอธิบายมากมายเกี่ยวกับวิธีการใช้งาน)

จากนั้นในกล่อง Windows ฉันสร้างคลาส Python 3 ด้านล่างเพื่อสร้างลิงก์

สามารถใช้เพื่อสร้างลิงก์ไปยังการแชร์ Windows

แต่คำตอบสั้น ๆ คือ - สร้างการแชร์บนกล่อง linux และใช้ mklink ใน command prompt เพื่อสร้างลิงค์สัญลักษณ์

คำเตือน: รหัสนี้มีความหมายเป็นหลักฐานพิสูจน์ของแนวคิด มันเป็นงานที่อยู่ระหว่างดำเนินการและไม่สมบูรณ์ ฉันไม่อ้างว่าเป็นรหัสที่ดีที่สุดหรือแม้แต่รหัสที่ดี

"""    
@Author: J. Michael Adams

Please cite the author's name if you use any of this code.

Creates symlinks for share folders

It places all the symlinks in a local folder. The test code defines that folder
as C:\share_symlinks.

NOTE -
This program uses the "mklink" command of the Windows command shell.
That command normally requires elevated administrator privilege.
That requirement can be changed using the "secpol.msc" console under
Security Settings > Local Policies > User Rights Assignment > create symbolic links

It pipes in a list of shares from the "net view" command.

Each output line from net view has this format: share-name "Disk" other-info
If it does not contain " Disk ", then it does not have a share name.

We want to create a symlink for each share.
The links will be created in a particular directory.

You can specify a list of share names that will be excluded - that is, they will
not be linked to. A name can can contain wildcards.

Any share name that matches a name in the exclude list will be ignored.
"""

#TODO: create a config file: excludes, link_dir, remote_drive, notify always, email parms
#TODO: check the permission level
#TODO: check the value of comspec
#TODO: remove obsolete links - links that have the proper remote_drive
#TODO: create an email object for notification
#TODO: create an exception that emails a notification

import os
import subprocess

class LinkManager(object):

    def __init__(self, remote_drive):
        self.remote_drive = remote_drive

        self.share_paths = {}  # share_paths[share name] => full path to share
        self.new_links = {}
        self.all_links = {}
        self.bad_links = {}

    def get_shares(self, excludes=None):

        """ returns a dict: key = share name, value = full path to the share

        """

        import fnmatch

        if type(excludes) is not list:
            if excludes is None:
                excludes = []
            elif type(excludes) is str:
                excludes = [excludes]
            else:
                raise Exception

        # Always exclude shares that end with '$'. These are administrative shares in Windows.
        excludes.append('*$')
        # We want to ignore case when we compare strings in the excludes list.
        # So we'll convert all share names to lower case.
        excludes = [x.lower() for x in excludes]

        ## call net view for the share drive. This might produce "access denied".
        # http://stackoverflow.com/questions/3005437/windowserror-error-5-access-is-denied
        cmd = "net view {} /all".format(remote_drive)

        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                shell=True, universal_newlines=True)
        (out, err) = proc.communicate()

        if err:
            return out, err  #TODO: should be an exception

        ## get the output of the command and parse the share names
        # we'll convert all lines to lower case.
        # Since this is Windows, file names are case insensitive.
        # We do this so we can compare to the lower case names in the exclude list.
        lines = out.lower().split('\n')

        for line in lines:

            # search for " disk " surrounded by a space, in case "disk" is a share name.
            if " disk " not in line:
                continue

            share = line.split(' disk ')[0].strip()

            # Check the share name against the exclude list.
            # The list can have names with wildcards ('*' and '?'),
            # so we'll use fnmatch() to check it.
            found = False
            for exclude in excludes:
                if fnmatch.fnmatch(share, exclude):
                    found = True
                    break
            if found:
                continue

            self.share_paths[share] = os.path.join(remote_drive, share)

        return '', ''

    def make_links(self, link_dir):

        """
         link_dir is the full path to the directory that will contain the links
         self.share_paths is a dict: share-name => target

         returns 3 dicts:
                new_links: a dict of all newly created links,
                all_links: a dict of all links in the link directory
                bad_links: links that do not point to the share base.

                key = link (full path)
                value = target (full path)

                for bad_link: if the value is None, the link path is not a link
         a dict of created links:
        """

        result = []
        for share, path in self.share_paths.items():

            # Create a symlink to the link directory.

            link = os.path.join(link_dir, share)

            self.all_links[link] = path

            # If it's already a link, it should point to the proper place
            # If the link name exists, but it's not a link
            # it's an error (or at least an issue).
            if os.path.exists(link):
                if os.path.islink(link):
                    relative_target = os.readlink(link)
                    target = os.path.realpath(relative_target)
                    if target != path:
                        self.bad_links[link] = target
                else:
                    self.bad_links[link] = None
                continue

            proc = subprocess.Popen(["mklink", "/D", link, path],
                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                    shell=True)
            (out, err) = proc.communicate()
            #TODO: check the output. err should be empty. out should not be.
            print("program output: ", out)
            print("program err: ", err)

            self.new_links[link] = path

            result.append((out, err))

        return

    def remove_obsolete(self):

        # for each link in the directory, see if the name is a share. If not, remove it.
        #TODO: code it.
        pass
    def remove_link(self, link):

        if os.path.islink(link):
            # This removes the link, not the target
            proc = subprocess.Popen(["rmdir", link], stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE, shell=True)
            (out, err) = proc.communicate()
        else:
            out = ''
            err = "{} is not a link".format(link)

        return out, err

    # send an email to server_notifications


############## TEST ############################

#############################
# define the shares that will not be linked to.
# The routine "get_shares() will add the entry '*$' to the
# exclude list.
#############################

excludes = ['trash', 'home', 'Users']


link_dir = r'C:\share_symlinks'
remote_drive = r'\\bilbao'

mgr = LinkManager(remote_drive)

mgr.get_shares(excludes)
mgr.make_links(link_dir)

testing = False
if testing:
    for link, full_share in mgr.all_links.items():

        sysout, syserr = mgr.remove_link(link)
        # both err and out should be blank

        print('rmdir out: {}'.format(sysout))
        print('rmdir err: {}'.format(syserr))

        continue

exit(0)

1

หากคุณไม่สามารถเปลี่ยนโฟลเดอร์ในการตั้งค่าของโปรแกรมได้คุณอาจทำอะไรไม่ได้เลยโดยสร้างเป้าหมาย iSCSI บน Linux PC ของคุณ ( อาจเป็นเป้าหมายไฟล์เพื่อให้พาร์ติชันของคุณยังคงอยู่) และใช้ iSCSI initiator บน Windows VM ของคุณ เชื่อมต่อกับมัน ( MS iSCSI ริเริ่ม , StarWind iSCSI Initiator )

อีกวิธีหนึ่งสามารถแก้ไขโปรแกรม hex และชี้ไปที่ไดรฟ์เครือข่ายที่แมป แต่ที่ต้องใช้ทักษะบางอย่าง

UPDATE:ฉันได้พบวิธีแก้ปัญหาที่ดูมีแนวโน้มและไม่ต้องยุ่งกับ iSCSI: มีวิธีการแมปเส้นทาง UNC ไปยังโฟลเดอร์ท้องถิ่นใน Windows 2003 หรือไม่? . ดูเหมือนว่าmklinkจะสามารถทำแผนที่เครือข่ายหุ้น (อัปยศกับฉันฉันควรจะได้ตรวจสอบ) และถ้ามันล้มเหลวคุณสามารถลองLink คูสัญลักษณ์สำหรับ Windows XP


ขอบคุณ ที่ดูมีแนวโน้มสวย ฉันค่อนข้างชัดเจนเกี่ยวกับวิธีการตั้งค่าเป้าหมายบนเครื่อง Linux ที่พิจารณาข้อความนี้: "ชื่อเป้าหมายต้องเป็นชื่อที่ไม่ซ้ำกันทั่วโลกมาตรฐาน iSCSI กำหนด" iSCSI Qualified Name "ดังนี้: iqn.yyyy-mm . <reverse domain name> [: identifier]; yyyy-mm เป็นวันที่โดเมนนั้นถูกต้องตัวระบุนั้นสามารถเลือกได้อย่างอิสระ "ว่าจะยังใช้งานได้เพราะเครื่องสองเครื่องนั้นอยู่ในเครือข่ายท้องถิ่นหรือไม่? นอกจากนี้ตามความเห็นของคุณคุณคิดว่าจะเป็นการดีกว่าหรือไม่ที่จะติดตั้งพาร์ติชันใหม่หรือใช้ไฟล์รูปภาพ?
Greg Nickoloff

@ g-man1066 ฉันคิดว่ามันอาจเป็นโดเมนใดก็ได้แม้จะเป็นตัวละครตราบใดที่มันเป็นไปตามข้อกำหนด ฉันจะใช้ชื่อโฮสต์ และฉันจะใช้ไฟล์รูปภาพดูง่ายกว่านี้ Btw ดูเหมือนว่าmklinkจะสามารถแมปเครือข่ายร่วมกันได้ดังนั้นฉันจึงอัปเดตคำตอบของฉันดูว่าช่วยได้ไหม
beatcracker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.